 
#include "Perceptron.h"

int main(int argc, const char* argv[])
{
	int nRetCode = 0;

	CImageEx::Initialize();

	if (1)
	{
		string strFN_Configuration		=	argv[1];
		string strOperation				=	argv[2];
		int TargetNodeIndex				=	atoi(argv[3]);

		strOperation += "00000000";
		int Op_Make_GT_Annotation		=	CDataStructureTools::Hex2Num(strOperation[0]);
		int Op_InitPerceptronModel		=	CDataStructureTools::Hex2Num(strOperation[1]);
		int Op_MakeCropGT				=	CDataStructureTools::Hex2Num(strOperation[2]);
		int Op_MakeBicExampleList		=	CDataStructureTools::Hex2Num(strOperation[3]);
		int Op_BoostTrainTest			=	CDataStructureTools::Hex2Num(strOperation[4]);
		int Op_TrainPerceptronModel		=	CDataStructureTools::Hex2Num(strOperation[5]);
		int Op_BoostDetect				=	CDataStructureTools::Hex2Num(strOperation[6]);
		int Op_PerceptronDetect			=	CDataStructureTools::Hex2Num(strOperation[7]);

		char strTemp[10001] = "";
		int sgnImageSet, sgnPosNeg, i_image, i_node, i_example, i_layer;
		sgnImageSet = sgnPosNeg = i_image = i_node = i_example = i_layer = 0;

		//////////	Config Loading	//////////

		CConfiguration Config(strFN_Configuration);
		Config.Load();

		string strFN_OutLog																	=	Config.GetString("strFN_OutLog", "xxx.log");

		GlobalHiBoostSettings.AbstractTree.myInit(												Config.GetString("strFN_MyAndTree"));
		and_or_tree::CAbstractTree& AbstractTree = GlobalHiBoostSettings.AbstractTree;

		GlobalHiBoostSettings.HiBoostExampleSettings.myInit(									Config.GetString("strFN_ExampleSettings"), AbstractTree.NodeAmount);

		GlobalHiBoostSettings.strFN_SelectedNodeList										=	Config.GetString("strFN_SelectedNodeList");
		GlobalHiBoostSettings.strFN_Original_Annotation_IgnoreList							=	Config.GetString("strFN_Original_Annotation_IgnoreList");

		CSimpleTypeArray<bool> fNodeSelectedList;
		CSimpleTypeArray<int> SelectedNodeColorList;
		fNodeSelectedList.Resize(AbstractTree.NodeAmount);
		fNodeSelectedList.Fill(false);
		SelectedNodeColorList.Resize(AbstractTree.NodeAmount);
		SelectedNodeColorList.Fill(0);
		{
			ifstream inFile(GlobalHiBoostSettings.strFN_SelectedNodeList.c_str());
			int t, rr, gg, bb;
			while (inFile>>t>>rr>>gg>>bb)
			{
				if (t>=0 && t<AbstractTree.NodeAmount)
				{
					fNodeSelectedList.pElement[t] = true;
					if (rr<0 || gg<0 || bb<0)
						SelectedNodeColorList.pElement[t] = AbstractTree.GetNodeColor(t);
					else
						SelectedNodeColorList.pElement[t] = CExternalTools::GetIntRGB(rr, gg, bb);
				}
			}
		}

		GlobalHiBoostSettings.Amount_SrcImage_Train_Pos										=	Config.GetInt("Amount_SrcImage_Train_Pos");
		GlobalHiBoostSettings.Amount_SrcImage_Train_Neg										=	Config.GetInt("Amount_SrcImage_Train_Neg");
		GlobalHiBoostSettings.Amount_SrcImage_Test_Pos										=	Config.GetInt("Amount_SrcImage_Test_Pos");
		GlobalHiBoostSettings.Amount_SrcImage_Test_Neg										=	Config.GetInt("Amount_SrcImage_Test_Neg");
		GlobalHiBoostSettings.Amount_Original_Annotation_Train								=	Config.GetInt("Amount_Original_Annotation_Train");
		GlobalHiBoostSettings.Amount_Original_Annotation_Test								=	Config.GetInt("Amount_Original_Annotation_Test");
		GlobalHiBoostSettings.strPN_SrcImage_Train_Pos										=	Config.GetString("strPN_SrcImage_Train_Pos");
		GlobalHiBoostSettings.strPN_SrcImage_Train_Neg										=	Config.GetString("strPN_SrcImage_Train_Neg");
		GlobalHiBoostSettings.strPN_SrcImage_Test_Pos										=	Config.GetString("strPN_SrcImage_Test_Pos");
		GlobalHiBoostSettings.strPN_SrcImage_Test_Neg										=	Config.GetString("strPN_SrcImage_Test_Neg");
		GlobalHiBoostSettings.strPN_INRIA_Annotation_Train									=	Config.GetString("strPN_INRIA_Annotation_Train");
		GlobalHiBoostSettings.strPN_INRIA_Annotation_Test									=	Config.GetString("strPN_INRIA_Annotation_Test");
		GlobalHiBoostSettings.strPN_Original_Annotation_Train								=	Config.GetString("strPN_Original_Annotation_Train");
		GlobalHiBoostSettings.strPN_Original_Annotation_Test								=	Config.GetString("strPN_Original_Annotation_Test");

		GlobalHiBoostSettings.Amount_GT_Annotation_Train									=	Config.GetInt("Amount_GT_Annotation_Train");
		GlobalHiBoostSettings.Amount_GT_Annotation_Test										=	Config.GetInt("Amount_GT_Annotation_Test");
		GlobalHiBoostSettings.strPN_Base_GT_Annotation										=	Config.GetString("strPN_Base_GT_Annotation");
		GlobalHiBoostSettings.strPN_Base_CropCT												=	Config.GetString("strPN_Base_CropCT");

		int Amount_PosExampleShake_ForTrain													=	Config.GetInt("Amount_PosExampleShake_ForTrain");
		GlobalHiBoostSettings.FileSetTag_for_BicParentFileName								=	Config.GetInt("FileSetTag_for_BicParentFileName");

		GlobalHiBoostSettings.strPN_ExampleList												=	Config.GetString("strPN_ExampleList");
		GlobalHiBoostSettings.strPN_Base_DrawExample										=	Config.GetString("strPN_Base_DrawExample");
		GlobalHiBoostSettings.strPN_Base_BoostModel											=	Config.GetString("strPN_Base_BoostModel");
		GlobalHiBoostSettings.strPN_Base_BoostDetect										=	Config.GetString("strPN_Base_BoostDetect");

		int Flag_Detect_ImageSet														=	Config.GetInt("Flag_Detect_ImageSet");
		int Flag_Detect_PosNeg															=	Config.GetInt("Flag_Detect_PosNeg");

		CHiBoostNodeInstanceBoxSet::s_Config.pTree = &AbstractTree;
		CHiBoostNodeInstanceBoxSet::s_Config.MinBoundingBoxRelativeScale_X					=	0.320;
		CHiBoostNodeInstanceBoxSet::s_Config.MinBoundingBoxRelativeScale_Y					=	0.125;

		//CHiBoostNodeInstanceBoxSet::s_Config.pTree = &AbstractTree;
		//CHiBoostNodeInstanceBoxSet::s_Config.MinBoundingBoxRelativeScale_X		=	Config.GetDouble("MinBoundingBoxRelativeScale_X");
		//CHiBoostNodeInstanceBoxSet::s_Config.MinBoundingBoxRelativeScale_Y		=	Config.GetDouble("MinBoundingBoxRelativeScale_Y");

		//int CropGT_Sample_GlobalObject_Tight_W					=	Config.GetInt("CropGT_Sample_GlobalObject_Tight_W");
		//int CropGT_Sample_GlobalObject_Tight_H					=	Config.GetInt("CropGT_Sample_GlobalObject_Tight_H");
		//int CropGT_Sample_GlobalObject_Loose_W					=	Config.GetInt("CropGT_Sample_GlobalObject_Loose_W");
		//int CropGT_Sample_GlobalObject_Loose_H					=	Config.GetInt("CropGT_Sample_GlobalObject_Loose_H");

		//CHiBoostExampleConfig HiBoostExampleConfig;
		//HiBoostExampleConfig.myInit(
		//	&AbstractTree, &HiBoostNodeContextConfig,
		//	Config.GetInt("Parse_ObjectExtent"),
		//	Config.GetInt("Parse_PartExtent"),
		//	Config.GetInt("Parse_StdObjectBoundingBox_W"),
		//	Config.GetInt("Parse_StdObjectBoundingBox_H"),
		//	Config.GetDouble("Parse_CropGT_xInferenceScale", 1.0),
		//	Config.GetDouble("Parse_CropGT_yInferenceScale", 1.0),
		//	GlobalHiBoostSettings.strPN_Base_CropGT);

		bool Flag_UseNegExampleOnPosImage = (1 ==												Config.GetInt("Flag_UseNegExampleOnPosImage", 1));

		double Scan_ScaleFactor_ForTrain													=	Config.GetDouble("Scan_ScaleFactor_ForTrain");
		int Scan_PixelSampleMargin_ForTrain													=	Config.GetInt("Scan_PixelSampleMargin_ForTrain");
		double Scan_PixelSampleRate_ForTrain												=	Config.GetDouble("Scan_PixelSampleRate_ForTrain");

		double Scan_ScaleFactor_ForDetect													=	Config.GetDouble("Scan_ScaleFactor_ForDetect");
		int Scan_PixelSampleMargin_ForDetect												=	Config.GetInt("Scan_PixelSampleMargin_ForDetect");
		double Scan_PixelSampleRate_ForDetect												=	Config.GetDouble("Scan_PixelSampleRate_ForDetect");

		double BoostDetect_TargetFPR														=	Config.GetDouble("BoostDetect_TargetFPR");

		int Amount_DrawExampleSample_Pos													=	Config.GetInt("Amount_DrawExampleSample_Pos");
		int Amount_DrawExampleSample_Neg													=	Config.GetInt("Amount_DrawExampleSample_Neg");

		int MemoryUsage_in_MB																=	Config.GetInt("MemoryUsage_in_MB", 1024);

		CCascadedAdaBoostParametersConfig CascadeConfig;
		CascadeConfig.AdaBoostConfig.fDetermineLayerThresholdUsingValSet					=	false;
		CascadeConfig.AdaBoostConfig.SFC_BinAmount											=	Config.GetInt("Boost_Ada_SFC_BinAmount");
		CascadeConfig.AdaBoostConfig.SFC_FeatureSampleRate									=	Config.GetDouble("Boost_Ada_SFC_FeatureSampleRate");
		CascadeConfig.AdaBoostConfig.DataSetUpdatingFrequency								=	Config.GetInt("Boost_Feature_UpdatingFrequency");
		CascadeConfig.TrainFeatureGroupAmount												=	Config.GetInt("Boost_Feature_GroupAmount");
		CascadeConfig.MaxLayerAmount														=	Config.GetInt("Boost_Cascade_LayerAmount");
		CascadeConfig.InitLayerTrainingEndConditionList(										Config.GetString("Boost_Cascade_strFN_LayerConfidion"));
		int Cascade_StartTrainingLayer														=	Config.GetInt("Boost_Cascade_StartTrainingLayer", 0);
		CascadeConfig.MaxTrainPosExampleAmount												=	Config.GetInt("Boost_Cascade_MaxTrainPosAmount", -1);
		CascadeConfig.MinTrainPosExampleAmount												=	Config.GetInt("Boost_Cascade_MinTrainPosAmount", -1);
		CascadeConfig.MaxTrainNegExampleAmount												=	Config.GetInt("Boost_Cascade_MaxTrainNegAmount", -1);
		CascadeConfig.MinTrainNegExampleAmount												=	Config.GetInt("Boost_Cascade_MinTrainNegAmount", -1);
		CascadeConfig.FeatureMemoryUsage_Pos_Train											=	MemoryUsage_in_MB * 4 / 17;
		CascadeConfig.FeatureMemoryUsage_Pos_Val											=	MemoryUsage_in_MB * 1 / 17;
		CascadeConfig.FeatureMemoryUsage_Train												=	MemoryUsage_in_MB * 8 / 17;
		CascadeConfig.FeatureMemoryUsage_Val												=	MemoryUsage_in_MB * 4 / 17;

		CHiBoostNodeSetAppearanceIPFE::s_IFB_ImageExtent									=	Config.GetInt("Feature_ImageExtent", 16);
		CHiBoostNodeSetAppearanceIPFE::s_IFB_TextonSigma									=	Config.GetDouble("Feature_TextonSigma", 0.7);
		CHiBoostNodeSetAppearanceIPFE::s_strPN_IFB_Cache									=	Config.GetString("Feature_strPN_IFB_Cache", "FilterCache\\");
		CHiBoostNodeSetAppearanceIPFE::s_pTree												=	&GlobalHiBoostSettings.AbstractTree;
		CHiBoostNodeSetAppearanceIPFE::s_SPL_List_A.Resize(AbstractTree.NodeAmount);
		CHiBoostNodeSetAppearanceIPFE::s_SPL_List_B.Resize(AbstractTree.NodeAmount);
		CHiBoostNodeSetAppearanceIPFE::s_SPL_List_C.Resize(AbstractTree.NodeAmount);
		CHiBoostNodeSetAppearanceIPFE::s_SPL_List_D.Resize(AbstractTree.NodeAmount);
		{
			CShapePattern_SingleCellInBlock tCell;
			CShapePatternList spl;
			int i;

			double a13 = 1.0/3;
			double a23 = 2.0/3;

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_2x2;
			CellList_2x2.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 0.5, 0.5); tCell.Weight = +1.0; CellList_2x2.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, 0.5, 0.5, 0.5); tCell.Weight = +1.0; CellList_2x2.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.0, 0.5, 0.5); tCell.Weight = +1.0; CellList_2x2.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.5, 0.5, 0.5); tCell.Weight = +1.0; CellList_2x2.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_2x1;
			CellList_2x1.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 0.5, 1.0); tCell.Weight = +1.0; CellList_2x1.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.0, 0.5, 1.0); tCell.Weight = +1.0; CellList_2x1.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_1x2;
			CellList_1x2.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 1.0, 0.5); tCell.Weight = +1.0; CellList_1x2.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, 0.5, 1.0, 0.5); tCell.Weight = +1.0; CellList_1x2.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_3x1;
			CellList_3x1.Clear();
			tCell.RatioBox.x = 0.0; tCell.RatioBox.y = 0.0; tCell.RatioBox.w = a13; tCell.RatioBox.h = 1.0; tCell.Weight = +1.0; CellList_3x1.PushBack(tCell);
			tCell.RatioBox.x = a13; tCell.RatioBox.y = 0.0; tCell.RatioBox.w = a13; tCell.RatioBox.h = 1.0; tCell.Weight = +1.0; CellList_3x1.PushBack(tCell);
			tCell.RatioBox.x = a23; tCell.RatioBox.y = 0.0; tCell.RatioBox.w = a13; tCell.RatioBox.h = 1.0; tCell.Weight = +1.0; CellList_3x1.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_1x3;
			CellList_1x3.Clear();
			tCell.RatioBox.x = 0.0; tCell.RatioBox.y = 0.0; tCell.RatioBox.w = 1.0; tCell.RatioBox.h = a13; tCell.Weight = +1.0; CellList_1x3.PushBack(tCell);
			tCell.RatioBox.x = 0.0; tCell.RatioBox.y = a13; tCell.RatioBox.w = 1.0; tCell.RatioBox.h = a13; tCell.Weight = +1.0; CellList_1x3.PushBack(tCell);
			tCell.RatioBox.x = 0.0; tCell.RatioBox.y = a23; tCell.RatioBox.w = 1.0; tCell.RatioBox.h = a13; tCell.Weight = +1.0; CellList_1x3.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_1x1;
			CellList_1x1.Clear();
			tCell.RatioBox.x = 0.0; tCell.RatioBox.y = 0.0; tCell.RatioBox.w = 1.0; tCell.RatioBox.h = 1.0; tCell.Weight = +1.0; CellList_1x1.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_ViolaJones_A;
			CellList_ViolaJones_A.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 0.5, 1.0); tCell.Weight = +1.0; CellList_ViolaJones_A.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.0, 0.5, 1.0); tCell.Weight = -1.0; CellList_ViolaJones_A.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_ViolaJones_B;
			CellList_ViolaJones_B.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 1.0, 0.5); tCell.Weight = +1.0; CellList_ViolaJones_B.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, 0.5, 1.0, 0.5); tCell.Weight = -1.0; CellList_ViolaJones_B.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_ViolaJones_C;
			CellList_ViolaJones_C.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, a13, 1.0); tCell.Weight = +1.0; CellList_ViolaJones_C.PushBack(tCell);
			tCell.RatioBox.myInit(a13, 0.0, a13, 1.0); tCell.Weight = -2.0; CellList_ViolaJones_C.PushBack(tCell);
			tCell.RatioBox.myInit(a23, 0.0, a13, 1.0); tCell.Weight = +1.0; CellList_ViolaJones_C.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_ViolaJones_D;
			CellList_ViolaJones_D.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 1.0, a13); tCell.Weight = +1.0; CellList_ViolaJones_D.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, a13, 1.0, a13); tCell.Weight = -2.0; CellList_ViolaJones_D.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, a23, 1.0, a13); tCell.Weight = +1.0; CellList_ViolaJones_D.PushBack(tCell);

			CSimpleTypeArray<CShapePattern_SingleCellInBlock> CellList_ViolaJones_E;
			CellList_ViolaJones_E.Clear();
			tCell.RatioBox.myInit(0.0, 0.0, 0.5, 0.5); tCell.Weight = +1.0; CellList_ViolaJones_E.PushBack(tCell);
			tCell.RatioBox.myInit(0.0, 0.5, 0.5, 0.5); tCell.Weight = -1.0; CellList_ViolaJones_E.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.0, 0.5, 0.5); tCell.Weight = -1.0; CellList_ViolaJones_E.PushBack(tCell);
			tCell.RatioBox.myInit(0.5, 0.5, 0.5, 0.5); tCell.Weight = +1.0; CellList_ViolaJones_E.PushBack(tCell);

			for ( i = 0; i < AbstractTree.NodeAmount; ++i )
			{
				double ww, hh, cw, ch;
				GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeFeatureContextSettings(ww, hh, cw, ch, i);
				//const CHiBoostNodeContextConfig::CNode& tc = HiBoostNodeContextConfig.GetDataForNode(i);

				spl.Clear();
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 1.0, ch * 1.0, cw * 1.0, ch * 1.0, CellList_1x1);
				CHiBoostNodeSetAppearanceIPFE::s_SPL_List_A.pElement[i] = spl;

				spl.Clear();
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw * 1.0, ch * 1.0, CellList_ViolaJones_E);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 1.0, ch * 2.0, cw * 1.0, ch * 1.0, CellList_ViolaJones_A);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 1.0, cw * 1.0, ch * 1.0, CellList_ViolaJones_B);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 1.0, cw * 1.0, ch * 1.0, CellList_ViolaJones_C);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 1.0, ch * 2.0, cw * 1.0, ch * 1.0, CellList_ViolaJones_D);
				CHiBoostNodeSetAppearanceIPFE::s_SPL_List_B.pElement[i] = spl;

				spl.Clear();
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw, ch, CellList_2x2);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw, ch, CellList_2x1);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw, ch, CellList_1x2);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw, ch, CellList_3x1);
				CShapePatternList::GenBlockPattern(spl, true, 0.0, 0.0,
					ww, hh, cw * 2.0, ch * 2.0, cw, ch, CellList_1x3);
				CHiBoostNodeSetAppearanceIPFE::s_SPL_List_C.pElement[i] = spl;
			}
		}

		string strFN_Perceptron_NewStructure					=	Config.GetString("strFN_Perceptron_NewStructure", "NewFormat.Structure.txt");
		string strFN_Perceptron_InitializedModel				=	Config.GetString("strFN_Perceptron_InitializedModel", "HiBoost.InitModel.txt");
		string strPN_Perceptron_GT_Instance_Train				=	Config.GetString("strPN_Perceptron_GT_Instance_Train", "GT.Inst.Text.Train\\");
		string strPN_Perceptron_GT_Image_Train					=	Config.GetString("strPN_Perceptron_GT_Image_Train", "GT.Inst.Show.Train\\");
		string strPN_Perceptron_GT_Instance_Test				=	Config.GetString("strPN_Perceptron_GT_Instance_Test", "GT.Inst.Text.Test\\");
		string strPN_Perceptron_GT_Image_Test					=	Config.GetString("strPN_Perceptron_GT_Image_Test", "GT.Inst.Show.Test\\");
		string strPN_Perceptron_ParseLog_Train					=	Config.GetString("strPN_Perceptron_ParseLog_Train", "ParseLog.Train\\");
		string strPN_Perceptron_TrainedModel					=	Config.GetString("strPN_Perceptron_TrainedModel", "PercetronModel\\");
		CMyTreeInstance::s_DetectionNMS_AOP_Thrshold			=	Config.GetDouble("Perceptron_Detection_NMS_Threshold", 0.7);

		GlobalHiBoostSettings.strFN_Perceptron_ModelForDetect	=	Config.GetString("strFN_Perceptron_ModelForDetect");
		GlobalHiBoostSettings.strPN_Perceptron_DetectBase		=	Config.GetString("strPN_Perceptron_DetectBase");
		GlobalHiBoostSettings.strPN_Perceptron_ParseLog_Detect	=	Config.GetString("strPN_Perceptron_ParseLog_Detect", "ParseLog.Detect\\");

		// Start Perceptron Settings

		GlobalHiBoostSettings.strPN_Perceptron_ImageCache		=	Config.GetString("strPN_Perceptron_ImageCache");

		CImagePixelSampler_EdgeAndRandom IPS_ForInference;
		IPS_ForInference.ColorMode = CImagePixelSampler_EdgeAndRandom::COLOR_MODE_RGB;
		IPS_ForInference.Canny_GaussianSigma = 2.0;
		IPS_ForInference.Canny_tLow = 0.40;
		IPS_ForInference.Canny_tHigh = 0.80;
		IPS_ForInference.Edge_LengthThreshold = -1; // 10;
		IPS_ForInference.Edge_DirectionThreshold = PI / 6.0;
		IPS_ForInference.Edge_SampleRate = 1.0;
		IPS_ForInference.Random_SampleMargin = 7;
		IPS_ForInference.Random_SampleRate = 1.0;
		IPS_ForInference.BoundaryMargin = 0;
		IPS_ForInference.Prepare();

		CImagePixelSampler_EdgeAndRandom IPS_ForAppearance;
		//IPS_ForAppearance.ColorMode = CImagePixelSampler_EdgeAndRandom::COLOR_MODE_GRAY;
		//IPS_ForAppearance.Canny_GaussianSigma = 1.0;
		//IPS_ForAppearance.Canny_tLow = 0.30;
		//IPS_ForAppearance.Canny_tHigh = 0.60;
		IPS_ForAppearance.Edge_LengthThreshold = -1;
		//IPS_ForAppearance.Edge_DirectionThreshold = PI / 6.0;
		IPS_ForAppearance.Edge_SampleRate = 1.0;
		IPS_ForAppearance.Random_SampleMargin = 7;
		IPS_ForAppearance.Random_SampleRate = 1.0;
		IPS_ForAppearance.BoundaryMargin = 0;
		IPS_ForAppearance.Prepare();

		CHiBoostImageEntity::s_Config.pExampleSettings = &GlobalHiBoostSettings.HiBoostExampleSettings;
		CHiBoostImageEntity::s_Config.ScaleFactor_AppearanceModel = 1.33;
		CHiBoostImageEntity::s_Config.ScaleFactor_PerceptronParser = 1.33;
		CHiBoostImageEntity::s_Config.IPFE_CacheSize = 5;
		CHiBoostImageEntity::s_Config.FixedBcPtrList.Clear();
		CSimpleTypeArray<CCascadedAdaBoostClassifier> cabcList;
		{
			cabcList.Resize(AbstractTree.NodeAmount);
			for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
			{
				GlobalHiBoostSettings.MakeFN_BoostModel(strTemp, i_node);
				cabcList.pElement[i_node].LoadFromFile(strTemp);
				CHiBoostImageEntity::s_Config.FixedBcPtrList.PushBack(cabcList.pElement + i_node);
			}
		}
		CHiBoostImageEntity::s_Config.pIPS_ForInference = &IPS_ForInference;
		CHiBoostImageEntity::s_Config.pIPS_ForAppearance = &IPS_ForAppearance;
		CHiBoostImageEntity::s_Config.GradientComputing_GaussianSigma = 1.0;
		CHiBoostImageEntity::s_Config.GradientComputing_fUseSignedOrientation = false;
		CHiBoostImageEntity::s_Config.LayerMinWidth = 64;
		CHiBoostImageEntity::s_Config.LayerMinHeight = 128;

		CMeanShiftNMS::CParameters MeanShiftConfig_ForPerceptronDetect;
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.dx = (IPS_ForInference.Random_SampleMargin + 1.0);
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.dy = (IPS_ForInference.Random_SampleMargin + 1.0);
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.dw = 1.3;
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.dh = 1.3;
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.scale = 1.0;
		MeanShiftConfig_ForPerceptronDetect.KernelConfig.tfMode = CMeanShiftNMS::TFMODE_HARD;

		CHiBoostGroundTruthList GT_List_Train;
		CHiBoostGroundTruthList GT_List_Test;

		ofstream outLog(strFN_OutLog.c_str());

		// ********** Main Code Start **********
		if (1)
		{
			if (Op_Make_GT_Annotation & 1)
			{
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Base_GT_Annotation);

				int i, j, o, q;
				int iiAmount_train, iiAmount_test, iiAmount_all;
				set<int> train_pos_ignore_set;
				set<int> test_pos_ignore_set;
				train_pos_ignore_set.clear();
				test_pos_ignore_set.clear();
				{
					ifstream inIgnoreList(GlobalHiBoostSettings.strFN_Original_Annotation_IgnoreList.c_str());
					set<int>* pis;
					for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
					{
						if (sgnImageSet==0)
							pis = &train_pos_ignore_set;
						else
							pis = &test_pos_ignore_set;
						while (inIgnoreList>>i && i>=0)
							pis->insert(i);
					}
					inIgnoreList.clear();
					inIgnoreList.close();
				}
				iiAmount_train = (int)train_pos_ignore_set.size();
				iiAmount_test = (int)test_pos_ignore_set.size();
				iiAmount_all = iiAmount_train + iiAmount_test;

				for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
				{
					CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.GetPN_GT_Annotation(sgnImageSet));
					CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.GetPN_GT_AnnExample(sgnImageSet));

					int Amount_GT = 0;
					int Amount_Original_Annotation = GlobalHiBoostSettings.GetAmount_Original_Annotation(sgnImageSet);

					int i_material, j_gt_box;
					CSimpleTypeArray<CRectBox<int>> GtList;
					i_material = -1; j_gt_box = 0;
					GtList.Clear();

					CRectBox<int> CurrentGtBox;

					CImg<int> imgSrcImage;
					CImg<int> imgNew;
					int iw_org, ih_org;

					CImg<int> imgLabeled;
					int iw_lbl, ih_lbl;

					double sc1;
					double cx, cy;
					double tt, ttx, tty, tx2, ty2;
					CSimpleTypeArray<int> q_list;
					CSimpleTypeArray<double> ttx_list;
					CSimpleTypeArray<double> tty_list;

					CSimpleTypeArray<int> SampledPixelList;
					CImagePixelSampler_EdgeAndRandom ips;
					CImagePositionQueryAnswerer iqa;
					const CImagePositionQueryAnswerer::CPixRef* ppr;
					ips.ColorMode = CImagePixelSampler_EdgeAndRandom::COLOR_MODE_RGB;
					ips.Random_SampleMargin = 3;
					ips.Prepare();

					for ( i = 0; i < Amount_Original_Annotation; ++i )
					{
						GlobalHiBoostSettings.MakeFN_Original_Ann__Image(strTemp, sgnImageSet, i);
						CExternalTools::myLoadImage(strTemp, imgLabeled);
						iw_lbl = imgLabeled.dimx();
						ih_lbl = imgLabeled.dimy();

						for ( ++j_gt_box; (i_material<0 || j_gt_box>=(int)GtList.Size); )
						{
							++i_material;
							j_gt_box = 0;

							GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, 1, i_material);
							CExternalTools::myLoadImage(strTemp, imgSrcImage);
							iw_org = imgSrcImage.width;
							ih_org = imgSrcImage.height;

							GlobalHiBoostSettings.MakeFN_INRIA_Annotation(strTemp, sgnImageSet, i_material);
							CGroundTruthReader_INRIA::ReadGroundTruthFile(GtList, strTemp);
						}
						CurrentGtBox = GtList.pElement[j_gt_box];
						cx = CurrentGtBox.x + CurrentGtBox.w * 0.5;
						cy = CurrentGtBox.y + CurrentGtBox.h * 0.5;
						sc1 = 1.0 / sqrt(45000.0 / (CurrentGtBox.w * CurrentGtBox.h));

						if (sgnImageSet==0 && train_pos_ignore_set.find(i)!=train_pos_ignore_set.end()) continue;
						if (sgnImageSet==1 && test_pos_ignore_set.find(i)!=test_pos_ignore_set.end()) continue;

						imgNew = imgSrcImage;

						q_list.Clear();
						ttx_list.Clear();
						tty_list.Clear();
						ips.Work(SampledPixelList, imgLabeled);
						iqa.myInit(iw_lbl, ih_lbl, SampledPixelList, CImagePositionQueryAnswerer::DISTANCE_MODE_EUCLID);

						GlobalHiBoostSettings.MakeFN_Original_Annotation(strTemp, sgnImageSet, i);
						ifstream inFile_GT(strTemp);
						inFile_GT.getline(strTemp, MAX_PATH);
						inFile_GT>>j>>o;
						for ( j = 0; j < o; ++j )
						{
							inFile_GT>>q>>ttx>>tty>>tt;
							ttx += 0.5; tty += 0.5;

							tx2 = ttx; ty2 = tty;
							ttx = (ttx + 0.5 - iw_lbl * 0.5) * sc1 + cx;
							ttx = (ttx<0 ? 0 : (ttx>iw_org-EPS ? iw_org-EPS : ttx));
							tty = (tty + 0.5 - ih_lbl * 0.5) * sc1 + cy;
							tty = (tty<0 ? 0 : (tty>ih_org-EPS ? ih_org-EPS : tty));
							imgNew.draw_circle((int)ttx, (int)tty, 2, CExternalTools::GetIntArrayRGB(0, 0, 0));
							ttx = tx2; tty = ty2;

							ppr = iqa.FindNearestSampledPixel((int)ttx, (int)tty);
							ttx = ppr->x + 0.5;
							tty = ppr->y + 0.5;

							ttx = (ttx + 0.5 - iw_lbl * 0.5) * sc1 + cx;
							ttx = (ttx<0 ? 0 : (ttx>iw_org-EPS ? iw_org-EPS : ttx));

							tty = (tty + 0.5 - ih_lbl * 0.5) * sc1 + cy;
							tty = (tty<0 ? 0 : (tty>ih_org-EPS ? ih_org-EPS : tty));

							imgNew.draw_circle((int)ttx, (int)tty, 2, CExternalTools::GetIntArrayRGB(AbstractTree.GetNodeColor(AbstractTree.GetLeafNodeIndex(q))));

							q_list.PushBack(q);
							ttx_list.PushBack(ttx);
							tty_list.PushBack(tty);
						}
						inFile_GT.clear();
						inFile_GT.close();

						for ( int ii = 0; ii < 2; ++ii )
						{
							if (ii == 0)
							{
								GlobalHiBoostSettings.MakeFN_GT_AnnExample(strTemp, sgnImageSet, Amount_GT);
								CExternalTools::mySaveImage(strTemp, imgNew);
							}

							GlobalHiBoostSettings.MakeFN_GT_Annotation(strTemp, sgnImageSet, Amount_GT);
							ofstream outFile_GT(strTemp);
							outFile_GT<<i_material<<endl;
							outFile_GT<<j_gt_box<<endl;
							outFile_GT<<(ii==1)<<endl;
							outFile_GT<<o<<endl;
							outFile_GT.precision(9);
							for ( j = 0; j < o; ++j )
							{
								q = q_list.pElement[j];
								ttx = ttx_list.pElement[j];
								tty = tty_list.pElement[j];

								if (ii == 1)
								{
									if (q < 3)
										q = q;
									else
										q = 24 - q;
									ttx = iw_org - ttx;
								}

								outFile_GT<<'\t'<<q;
								outFile_GT<<'\t'<<fixed<<ttx;
								outFile_GT<<'\t'<<fixed<<tty;
								outFile_GT<<endl;
							}
							outFile_GT.clear();
							outFile_GT.close();

							++Amount_GT;
						}

						CExternalTools::ConsoleTools::ClearCurrentLine();
						sprintf_s(strTemp, "Restored annotation to original %s image %d / %d, [%d %d %d]", GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), i+1, Amount_Original_Annotation, Amount_GT, i_material, j_gt_box);
						cout<<strTemp;
					}
					CExternalTools::ConsoleTools::ClearCurrentLine();
					sprintf_s(strTemp, "Total annotation amount of %s image set = %d", GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), Amount_GT);
					cout<<strTemp<<endl;
					outLog<<strTemp<<endl;
				}
			} // (Op_Make_GT_Annotation & 1)

			GlobalHiBoostSettings.MakeGroundTruthSet(GT_List_Train, GT_List_Test);

			if (Op_InitPerceptronModel & 1)
			{
				CProposalTree ProposalTree;
				ProposalTree.MakeStandardModel(strFN_Perceptron_NewStructure, GT_List_Train, strPN_Perceptron_GT_Instance_Train, strPN_Perceptron_GT_Image_Train);
				ProposalTree.SaveAndOrTreeModel(strFN_Perceptron_InitializedModel);
			} // (Op_InitPerceptronModel & 1)

			if (Op_MakeCropGT & 3)
			{
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Base_CropCT);

				CProposalTree ProposalTree;
				ProposalTree.ReadAndOrTreeModel(strFN_Perceptron_InitializedModel);
				ProposalTree.PrepareModel();

				int i_node;
				int i_image;
				int i_leaf;

				//CSimpleTypeArray<double> ra;	ra.Resize(AbstractTree.NodeAmount);		ra.Fill(0.0);
				//CSimpleTypeArray<double> rs;	rs.Resize(AbstractTree.NodeAmount);		rs.Fill(0.0);
				//CSimpleTypeArray<double> max_a;	max_a.Resize(AbstractTree.NodeAmount);	max_a.Fill(0.0);
				//CSimpleTypeArray<double> max_w;	max_w.Resize(AbstractTree.NodeAmount);	max_w.Fill(0.0);
				//CSimpleTypeArray<double> max_h;	max_h.Resize(AbstractTree.NodeAmount);	max_h.Fill(0.0);
				//CSimpleTypeArray<double> min_a;	min_a.Resize(AbstractTree.NodeAmount);	min_a.Fill(0.0);
				//CSimpleTypeArray<double> min_w;	min_w.Resize(AbstractTree.NodeAmount);	min_w.Fill(0.0);
				//CSimpleTypeArray<double> min_h;	min_h.Resize(AbstractTree.NodeAmount);	min_h.Fill(0.0);
				for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
				{
					CImg<int> imgSrc;
					CHiBoostImageEntity iEntity;
					CHiBoostGroundTruth iGT;
					InstanceTreeType iTree;
					CMyTreeInstance iMTI;
					CHiBoostGroundTruthList* pCurrent_GT_List;

					if (sgnImageSet == 0)
					{
						//HiBoostExampleConfig.PartCenterOffset_mx.Resize(AbstractTree.NodeAmount); HiBoostExampleConfig.PartCenterOffset_mx.Fill(0.0);
						//HiBoostExampleConfig.PartCenterOffset_vx.Resize(AbstractTree.NodeAmount); HiBoostExampleConfig.PartCenterOffset_vx.Fill(0.0);
						//HiBoostExampleConfig.PartCenterOffset_my.Resize(AbstractTree.NodeAmount); HiBoostExampleConfig.PartCenterOffset_my.Fill(0.0);
						//HiBoostExampleConfig.PartCenterOffset_vy.Resize(AbstractTree.NodeAmount); HiBoostExampleConfig.PartCenterOffset_vy.Fill(0.0);

						pCurrent_GT_List = &GT_List_Train;
						if (!(Op_MakeCropGT & 1)) continue;
						//if (!(TargetDataSet_TrainTest & 1)) continue;
					}
					else
					{
						pCurrent_GT_List = &GT_List_Test;
						if (!(Op_MakeCropGT & 2)) continue;
						//if (!(TargetDataSet_TrainTest & 2)) continue;
					}

					for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
					{
						if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

						CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.GetPN_CropCT(i_node, sgnImageSet));
					}

					for ( i_image = 0; i_image < pCurrent_GT_List->Amount_GroundTruth; ++i_image )
					{
						pCurrent_GT_List->GetGroundTruth(iGT, imgSrc, i_image, 0.0);
						//imgSrc.display();

						iEntity.SetImage(imgSrc, "", false);
						iEntity.ReadParsedLeafInstances(&iGT);
						ProposalTree.ParseEntityGroundTruth(iTree, iEntity, false);
						ProposalTree.MakeMyTreeInstance(iMTI, iTree, 0, iEntity);

						for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
						{
							if (sgnImageSet == 0)
							{
								CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[i_node];
								double ox = ((iMTI.DetectionBox.x + iMTI.DetectionBox.w * 0.5) - tMNI.x) / tMNI.scale;
								double oy = ((iMTI.DetectionBox.y + iMTI.DetectionBox.h * 0.5) - tMNI.y) / tMNI.scale;
								//HiBoostExampleConfig.PartCenterOffset_mx.pElement[i_node] += ox;
								//HiBoostExampleConfig.PartCenterOffset_vx.pElement[i_node] += ox * ox;
								//HiBoostExampleConfig.PartCenterOffset_my.pElement[i_node] += oy;
								//HiBoostExampleConfig.PartCenterOffset_vy.pElement[i_node] += oy * oy;

								//TODO
							}

							if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

							const CBicExampleConfig& CurrentBicExampleConfig = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);

							if (0)
							{
								CImg<int> imgOutput;
								int target_w, target_h;
								CRectBox<double> dBox;
								int tii, tix, tiy, tr;
								double tdx, tdy;

								double NewImageLayerScale = iEntity.CurrentImageLayer.BaseImageLayerScale * 1.5;

								CZoomConfig ZoomConfig;
								ZoomConfig = iEntity.ZoomImage.BuildImage(imgOutput, NewImageLayerScale, NewImageLayerScale, CDenseImage::EXPANDING_MODE_EDGE);
								target_w = imgOutput.width;
								target_h = imgOutput.height;

								for ( i_leaf = 0; i_leaf < AbstractTree.LeafNodeAmount; ++i_leaf )
								{
									tii = AbstractTree.GetLeafNodeIndex(i_leaf);
									tdx = iMTI.NodeInstanceList.pElement[tii].x;
									tdy = iMTI.NodeInstanceList.pElement[tii].y;
									ZoomConfig.Work(tdx, tdy, tdx, tdy);
									tix = CMyMath::TranslateNumber_Floor(tdx);
									tiy = CMyMath::TranslateNumber_Floor(tdy);
									if (i_node==tii || AbstractTree.Is_A_AncestorOf_B(i_node, tii))
										tr = 3;
									else
										tr = 1;
									imgOutput.draw_circle(tix, tiy, tr, CExternalTools::GetIntArrayRGB(AbstractTree.GetNodeColor(tii)));
								}

								CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[i_node];
								CurrentBicExampleConfig.MakeContextBoxFromCenterAndIplScale(dBox, tMNI.x, tMNI.y, 1.0 / tMNI.scale);
								//HiBoostNodeContextConfig.GetContextBoxForNodeInstance(dBox, tMNI.x, tMNI.y, tMNI.scale, i_node);
								dBox.x *= NewImageLayerScale;
								dBox.y *= NewImageLayerScale;
								dBox.w *= NewImageLayerScale;
								dBox.h *= NewImageLayerScale;
								//tfmConfig.Work(dBox, dBox);
								CExternalTools::DrawRectBox(imgOutput, dBox, 255, 0, 0);

								sprintf_s(strTemp, "%sT.%04d.jpg", GlobalHiBoostSettings.GetPN_CropCT(i_node, sgnImageSet).c_str(), i_image);
								//GlobalHiBoostSettings.MakeFN_CropGT_Sample(strTemp, sgnImageSet, i_node, i_image);
								CExternalTools::mySaveImage(strTemp, imgOutput);
							}

							if (1)
							{
								CImg<int> imgOutput;
								CRectBox<double> dBox;
								int cw, ch;
								double tw, th;

								cw = CurrentBicExampleConfig.StdObjectContext_W;
								ch = CurrentBicExampleConfig.StdObjectContext_H;
								tw = CurrentBicExampleConfig.PosExample_xScale * (cw + CurrentBicExampleConfig.PosExample_ImageExtent * 2);
								th = CurrentBicExampleConfig.PosExample_yScale * (ch + CurrentBicExampleConfig.PosExample_ImageExtent * 2);
								//HiBoostExampleConfig.GetStdPartContextSize(cw, ch, i_node);
								//tw = HiBoostExampleConfig.CropGT_xInferenceScale * (cw + HiBoostExampleConfig.PartExtent * 2);
								//th = HiBoostExampleConfig.CropGT_yInferenceScale * (ch + HiBoostExampleConfig.PartExtent * 2);

								CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[i_node];
								CurrentBicExampleConfig.MakeContextBoxFromCenterAndIplScale(dBox, tMNI.x, tMNI.y, 1.0 / tMNI.scale);
								//HiBoostNodeContextConfig.GetContextBoxForNodeInstance(dBox, tMNI.x, tMNI.y, tMNI.scale, i_node);

								CZoomConfig ZoomConfig;
								ZoomConfig.myInit(
									CurrentBicExampleConfig.PosExample_xScale / tMNI.scale,
									CurrentBicExampleConfig.PosExample_yScale / tMNI.scale,
									dBox.x, dBox.y,
									CurrentBicExampleConfig.PosExample_xScale * CurrentBicExampleConfig.PosExample_ImageExtent,
									CurrentBicExampleConfig.PosExample_yScale * CurrentBicExampleConfig.PosExample_ImageExtent);
								//ZoomConfig.myInit(
								//	HiBoostExampleConfig.CropGT_xInferenceScale / tMNI.scale,
								//	HiBoostExampleConfig.CropGT_yInferenceScale / tMNI.scale,
								//	dBox.x, dBox.y, HiBoostExampleConfig.PartExtent, HiBoostExampleConfig.PartExtent);
								iEntity.ZoomImage.BuildImage(imgOutput, (int)(tw + 0.5), (int)(th + 0.5), ZoomConfig, CDenseImage::EXPANDING_MODE_EDGE);
								ZoomConfig.WorkOnBox(dBox, dBox);

								//CExternalTools::DrawRectBox(imgOutput, dBox, 0, 0, 255);

								GlobalHiBoostSettings.MakeFN_CropGT(strTemp, i_node, sgnImageSet, i_image);
								CExternalTools::mySaveImage(strTemp, imgOutput);
							}
						} // i_node

						sprintf_s(strTemp, "%s CropGT %d/%d;", GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), i_image+1, pCurrent_GT_List->Amount_GroundTruth);
						CExternalTools::ConsoleTools::ClearCurrentLine();
						cout<<strTemp;
						if (i_image == pCurrent_GT_List->Amount_GroundTruth-1)
							outLog<<strTemp<<endl;
					} // i_image

					cout<<endl;

					//if (sgnImageSet == 0)
					//{
					//	double m_ox, v_ox;
					//	double m_oy, v_oy;
					//	for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
					//	{
					//		//if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

					//		m_ox = HiBoostExampleConfig.PartCenterOffset_mx.pElement[i_node] / pCurrent_GT_List->Amount_GroundTruth;
					//		v_ox = HiBoostExampleConfig.PartCenterOffset_vx.pElement[i_node] / pCurrent_GT_List->Amount_GroundTruth;
					//		v_ox = v_ox - m_ox * m_ox;
					//		v_ox = sqrt(v_ox>EPS ? v_ox : 0.0);
					//		HiBoostExampleConfig.PartCenterOffset_mx.pElement[i_node] = m_ox;
					//		HiBoostExampleConfig.PartCenterOffset_vx.pElement[i_node] = v_ox;

					//		m_oy = HiBoostExampleConfig.PartCenterOffset_my.pElement[i_node] / pCurrent_GT_List->Amount_GroundTruth;
					//		v_oy = HiBoostExampleConfig.PartCenterOffset_vy.pElement[i_node] / pCurrent_GT_List->Amount_GroundTruth;
					//		v_oy = v_oy - m_oy * m_oy;
					//		v_oy = sqrt(v_oy>EPS ? v_oy : 0.0);
					//		HiBoostExampleConfig.PartCenterOffset_my.pElement[i_node] = m_oy;
					//		HiBoostExampleConfig.PartCenterOffset_vy.pElement[i_node] = v_oy;

					//		sprintf_s(strTemp, "Node %02d, PCO <x,y> = <%+5.1lf,%+5.1lf> v <%+5.1lf,%+5.1lf>; ",
					//			i_node,	m_ox, m_oy, v_ox, v_oy);
					//		cout<<strTemp<<endl;
					//		outLog<<strTemp<<endl;
					//	}

					//	HiBoostExampleConfig.SavePartCenterOffset();
					//}
				} // sgnImageSet
			} // (Op_MakeCropGT & 3)

			
			if (Op_MakeBicExampleList & 1)
			{
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_ExampleList);

				int i_node, i_image, i_layer;
				for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
				{
					int Amount_Pos_Image = GlobalHiBoostSettings.GetAmount_GT_Annotation(sgnImageSet);
					int Amount_Neg_Image_NegSrc = GlobalHiBoostSettings.GetAmount_SrcImage(sgnImageSet, 0);
					int Amount_Neg_Image_PosSrc = GlobalHiBoostSettings.GetAmount_SrcImage(sgnImageSet, 1);

					//int i_shake;
					//int cw, ch;
					//double ox, oy, sx, sy;

					for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
					{
						if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

						CBicExample tBicExample;
						CSimpleTypeArray<CBicExample> BicExampleList;
						BicExampleList.Clear();

						//CHiBoostExample tExample;
						//CSimpleTypeArray<CHiBoostExample> ExampleList;
						//ExampleList.Clear();

						CBicExampleConfig CurrentBicExampleConfigCopy = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);
						CurrentBicExampleConfigCopy.Scan_FitBox_Style = CBicExampleConfig::FIT_BOX_STYLE_CONTEXT;

						for ( i_image = 0; i_image < Amount_Pos_Image; ++i_image )
						{
							if (sgnImageSet == 1)
							{
								CurrentBicExampleConfigCopy.BuildPosExample(tBicExample,
									GlobalHiBoostSettings.GetBicParentFileNameSetIndex(sgnImageSet, 1, true), i_image);
								BicExampleList.PushBack(tBicExample);
								//HiBoostExampleConfig.BuildGroundTruthExample(tExample, i_node, i_image);
								//ExampleList.PushBack(tExample);
								continue;
							}
							CurrentBicExampleConfigCopy.GeneratePosExampleList(BicExampleList, true,
								GlobalHiBoostSettings.GetBicParentFileNameSetIndex(sgnImageSet, 1, true), i_image,
								Amount_PosExampleShake_ForTrain, true, true);

							//for ( i_shake = 0; i_shake < TrainPosShakeRange_Amount; ++i_shake )
							//{
							//	HiBoostExampleConfig.BuildGroundTruthExample(tExample, i_node, i_image);

							//	if (i_shake > 0)
							//	{
							//		HiBoostExampleConfig.GetStdPartContextSize(cw, ch, i_node);
							//		ox = cw * TrainPosShakeRange_xOffset / tExample.layer_scale_x;
							//		oy = ch * TrainPosShakeRange_yOffset / tExample.layer_scale_y;
							//		tExample.real_x += CMyRandom::NextDouble() * (ox + ox) - ox;
							//		tExample.real_y += CMyRandom::NextDouble() * (oy + oy) - oy;

							//		sx = log(TrainPosShakeRange_xScale);
							//		sy = log(TrainPosShakeRange_yScale);
							//		tExample.layer_scale_x *= exp(CMyRandom::NextDouble() * (sx + sx) - sx);
							//		tExample.layer_scale_y *= exp(CMyRandom::NextDouble() * (sy + sy) - sy);
							//	}

							//	ExampleList.PushBack(tExample);
							//}
						} // i_image

						sprintf_s(strTemp, "Node %02d In Total: %d Pos Examples", i_node, (int)BicExampleList.Size);
						//sprintf_s(strTemp, "Node %02d In Total: %d Pos Examples", i_node, (int)ExampleList.Size);
						CExternalTools::ConsoleTools::ClearCurrentLine();
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;

						CImg<int> imgSrcNegImage;
						int ow, oh;
						int tLayerExampleAmount;
						int sImageExampleAmount;

						i_image = 0;
						//Amount_Neg_Image_NegSrc = 0;
						for ( i_image = 0; i_image < Amount_Neg_Image_NegSrc; ++i_image )
						{
							GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, 0, i_image);
							CExternalTools::myLoadImage(strTemp, imgSrcNegImage);
							ow = imgSrcNegImage.width; oh = imgSrcNegImage.height;

							sImageExampleAmount = 0;
							for ( i_layer = 0; ; ++i_layer )
							{
								tLayerExampleAmount = CurrentBicExampleConfigCopy.GenerateNegExampleList(BicExampleList, true, ow, oh,
									Scan_PixelSampleMargin_ForTrain, Scan_PixelSampleRate_ForTrain, i_layer, Scan_ScaleFactor_ForTrain,
									GlobalHiBoostSettings.GetBicParentFileNameSetIndex(sgnImageSet, 0, false), i_image);
								//tLayerExampleAmount = HiBoostExampleConfig.AppendNegExamples(
								//	ExampleList, Train_SrcNegImage_PixelSampleMargin, Train_SrcNegImage_PixelSampleRate,
								//	ow, oh, i_layer, ScaleFactor_Train,
								//	i_node, true,
								//	i_image, false);
								if (tLayerExampleAmount < 1) break;
								sImageExampleAmount += tLayerExampleAmount;
							}

							if (i_image==Amount_Neg_Image_NegSrc-1 || CMyRandom::NextInt(Amount_Neg_Image_NegSrc/100)==0)
							{
								sprintf_s(strTemp, "Node %02d Neg Src Image %04d / %04d Level Amount %02d: %d / %d",
									i_node, i_image+1, Amount_Neg_Image_NegSrc, i_layer, sImageExampleAmount, (int)BicExampleList.Size);
								//sprintf_s(strTemp, "Node %02d Neg Src Image %04d / %04d Level Amount %02d: %d / %d",
								//	i_node, i_image+1, Amount_Neg_Image_NegSrc, i_layer, sImageExampleAmount, (int)ExampleList.Size);
								CExternalTools::ConsoleTools::ClearCurrentLine();
								cout<<strTemp;
								if (i_image == Amount_Neg_Image_NegSrc-1)
								{
									cout<<endl;
									outLog<<strTemp<<endl;
								}
							}
						} // i_image

						if (Flag_UseNegExampleOnPosImage)
						{
							double NegExample_AOP_Threshold = 0.4;

							CSimpleTypeArray<CRectBox<int>> GtBoxList;
							int j, o, cw, ch;
							double tAOP;
							CRectBox<double> dBox;
							for ( i_image = 0; i_image < Amount_Neg_Image_PosSrc; ++i_image )
							{
								GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, 1, i_image);
								CExternalTools::myLoadImage(strTemp, imgSrcNegImage);
								ow = imgSrcNegImage.width; oh = imgSrcNegImage.height;

								GlobalHiBoostSettings.MakeFN_INRIA_Annotation(strTemp, sgnImageSet, i_image);
								CGroundTruthReader_INRIA::ReadGroundTruthFile(GtBoxList, strTemp);

								for ( o = 0; o < (int)GtBoxList.Size; ++o ) CExternalTools::DrawRectBox(imgSrcNegImage, GtBoxList.pElement[o], 0);

								CSimpleTypeArray<CBicExample> bel_layer;

								sImageExampleAmount = 0;
								for ( i_layer = 0; ; ++i_layer )
								{
									tLayerExampleAmount = CurrentBicExampleConfigCopy.GenerateNegExampleList(bel_layer, false, ow, oh,
										Scan_PixelSampleMargin_ForTrain, Scan_PixelSampleRate_ForTrain, i_layer, Scan_ScaleFactor_ForTrain,
										GlobalHiBoostSettings.GetBicParentFileNameSetIndex(sgnImageSet, 1, false), i_image);
									if (tLayerExampleAmount < 1) break;

									cw = CurrentBicExampleConfigCopy.StdObjectContext_W;
									ch = CurrentBicExampleConfigCopy.StdObjectContext_H;
									tLayerExampleAmount = 0;
									for ( j = 0; j < (int)bel_layer.Size; ++j )
									{
										CurrentBicExampleConfigCopy.MakeTightBoxFromExample(dBox, bel_layer.pElement[j]);
										for ( o = 0; o < (int)GtBoxList.Size; ++o )
										{
											tAOP = CRectBox<double>::CalcAO_Percent(dBox, GtBoxList.pElement[o]);
											if (tAOP > NegExample_AOP_Threshold) break;
										}
										if (o >= (int)GtBoxList.Size)
											bel_layer.pElement[tLayerExampleAmount++] = bel_layer.pElement[j];
											//el_Layer.pElement[tLayerExampleAmount++] = te;
										else
										{
											CExternalTools::DrawRectBox(imgSrcNegImage, dBox, CMyRandom::NextInt(0x01000000));
										}
									}
									bel_layer.Resize(tLayerExampleAmount);
									BicExampleList.PushBack(bel_layer);

									sImageExampleAmount += tLayerExampleAmount;
								}

								if (i_image==Amount_Neg_Image_PosSrc-1 || CMyRandom::NextInt(Amount_Neg_Image_PosSrc/100)==0)
								{
									sprintf_s(strTemp, "Node %02d Pos Src Image %04d / %04d Level Amount %02d: %d / %d",
										i_node, i_image+1, Amount_Neg_Image_PosSrc, i_layer, sImageExampleAmount, (int)BicExampleList.Size);
									CExternalTools::ConsoleTools::ClearCurrentLine();
									cout<<strTemp;
									if (i_image == Amount_Neg_Image_PosSrc-1)
									{
										cout<<endl;
										outLog<<strTemp<<endl;
									}
								}
							} // i_image
						}

						sprintf_s(strTemp, "Node %02d In Total: %d Neg Examples", i_node, (int)BicExampleList.Size - Amount_Pos_Image);
						CExternalTools::ConsoleTools::ClearCurrentLine();
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;

						GlobalHiBoostSettings.MakeFN_ExampleList(strTemp, i_node, sgnImageSet);
						CBicExample::OutputListToFile(strTemp, BicExampleList);
					} // i_node
				} // sgnImageSet
			} // (Op_MakeBicExampleList & 1)

			//if (Op_MakeBicExampleList & 2)
			//{
			//	CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Base_DrawExample);

			//	CSimpleTypeArray<string> PosMaterialFileNameSet;
			//	CSimpleTypeArray<string> NegSrcImageFileNameSet;

			//	int i_node;
			//	int j, jj, ei;

			//	for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
			//	{
			//		GlobalHiBoostSettings.MakeFN_Set_SrcImage(NegSrcImageFileNameSet, sgnImageSet, 0, (sgnImageSet==0 ? GlobalHiBoostSettings.Amount_SrcImage_Train_Neg : GlobalHiBoostSettings.Amount_SrcImage_Test_Neg));

			//		if (sgnImageSet==0 && !(TargetDataSet_TrainTest & 1)) continue;
			//		if (sgnImageSet==1 && !(TargetDataSet_TrainTest & 2)) continue;

			//		for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
			//		{
			//			if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

			//			GlobalHiBoostSettings.MakeFN_Set_CropGT_Material(PosMaterialFileNameSet, sgnImageSet, i_node, (sgnImageSet==0 ? GlobalHiBoostSettings.Amount_GT_Annotation_Train : GlobalHiBoostSettings.Amount_GT_Annotation_Test));

			//			GlobalHiBoostSettings.MakePN_DrawExampleSample(strTmp2, sgnImageSet, i_node);
			//			CExternalTools::ConsoleTools::MakeDirectory(strTmp2, true);

			//			CDataSet_HiBoost_ByImage HiBoostDataSet;

			//			CHiBoostNodeSetAppearanceIPFE nsa;
			//			HiBoostDataSet.InitIPPFE(i_node, nsa.GetNodeAppearnceIPFE(i_node));

			//			GlobalHiBoostSettings.MakeFN_ExampleList(strTemp, i_node, sgnImageSet);
			//			HiBoostDataSet.InitExampleList(strTemp, GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), &PosMaterialFileNameSet, &NegSrcImageFileNameSet);
			//			{
			//				int cw, ch;
			//				HiBoostExampleConfig.GetStdPartContextSize(cw, ch, i_node);
			//				HiBoostDataSet.InitDrawContextSettings(cw, ch, 0); // HiBoostExampleConfig.PartExtent);
			//			}

			//			CDataSetForBinaryClassification bds;
			//			bds.SetRealDataSet(&HiBoostDataSet);
			//			bds.SetTargetLabel(+1);
			//			CBinaryClassificationExampleList FullExampleList;
			//			CBinaryClassificationExampleList SelectedExampleList;
			//			FullExampleList.myInit(&bds);
			//			SelectedExampleList.myInit(FullExampleList,
			//				1.0 * Amount_DrawExampleSample_Pos / FullExampleList.PosList.NodeAmount,
			//				1.0 * Amount_DrawExampleSample_Neg / FullExampleList.NegList.NodeAmount);

			//			CImg<int> imgDrawExampleSample;

			//			for ( sgnPosNeg = 0; sgnPosNeg < 2; ++sgnPosNeg )
			//			{
			//				if (sgnPosNeg == 1)
			//				{
			//					if (!(TargetDataSet_PosNeg & 1)) continue;
			//					jj = SelectedExampleList.PosList.NodeAmount;
			//				}
			//				else
			//				{
			//					if (!(TargetDataSet_PosNeg & 2)) continue;
			//					jj = SelectedExampleList.PosList.NodeAmount;
			//				}
			//				for ( j = 0; j < jj; ++j )
			//				{
			//					ei = (sgnPosNeg==1 ? SelectedExampleList.PosList : SelectedExampleList.NegList).rgExample[j].NodeIndex;
			//					HiBoostDataSet.SetQuery(ei);
			//					HiBoostDataSet.DrawExample(imgDrawExampleSample);
			//					GlobalHiBoostSettings.MakeFN_DrawExampleSample(strTemp, sgnImageSet, i_node, ei, bds.IsNodePositive(ei));
			//					CExternalTools::mySaveImage(strTemp, imgDrawExampleSample);

			//					sprintf_s(strTemp, "Draw Node %02d %s %s Example Sample: %d / %d", i_node,
			//						GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg), j+1, jj);
			//					CExternalTools::ConsoleTools::ClearCurrentLine();
			//					cout<<strTemp;
			//				}
			//				cout<<endl;
			//			} // sgnPosNeg
			//		} // i_node
			//	} // sgnImageSet
			//} // (Op_MakeBicExampleList & 2)

			if (Op_BoostTrainTest & 3)
			{
				CExternalTools::ConsoleTools::MakeDirectory(CHiBoostNodeSetAppearanceIPFE::s_strPN_IFB_Cache);
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Base_BoostModel);

				int i, j;

				for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
				{
					if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;

					CBicExampleConfig CurrentBicExampleConfigCopy = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);
					CurrentBicExampleConfigCopy.Scan_FitBox_Style = CBicExampleConfig::FIT_BOX_STYLE_CONTEXT;

					string strPN_BoostModel = GlobalHiBoostSettings.GetPN_BoostModel(i_node);
					if (Op_BoostTrainTest & 1)
						CExternalTools::ConsoleTools::MakeDirectory(strPN_BoostModel);

					CSimpleTypeArray<CBicExampleParentFileNameSet> List_FNS;
					GlobalHiBoostSettings.GenerateList_BicParentFileNameSet(List_FNS, i_node);

					if (Op_BoostTrainTest & 1)
					{
						CBicExampleFeatureDataSet HiBoostDataSet_Train;
						CDataSetForBinaryClassification bds_Train;
						CBinaryClassificationExampleList TrainExampleList;

						CBicExampleFeatureDataSet HiBoostDataSet_Test;
						CDataSetForBinaryClassification bds_Test;
						CBinaryClassificationExampleList TestExampleList;

						CHiBoostNodeSetAppearanceIPFE nsa;

						sgnImageSet = 0;
						HiBoostDataSet_Train.InitIPPFE(nsa.GetNodeAppearnceIPFE(i_node), 1);
						HiBoostDataSet_Train.InitBicExampleParentFileNameSetList(&List_FNS, "FOR_TRAIN.");
						GlobalHiBoostSettings.MakeFN_ExampleList(strTemp, i_node, sgnImageSet);
						HiBoostDataSet_Train.InitBicExampleList(strTemp);
						bds_Train.SetRealDataSet(&HiBoostDataSet_Train);
						bds_Train.SetTargetLabel(+1);
						TrainExampleList.myInit(&bds_Train);

						sgnImageSet = 1;
						HiBoostDataSet_Test.InitIPPFE(nsa.GetNodeAppearnceIPFE(i_node), 1);
						HiBoostDataSet_Test.InitBicExampleParentFileNameSetList(&List_FNS, "FOR_TRAIN.");
						GlobalHiBoostSettings.MakeFN_ExampleList(strTemp, i_node, sgnImageSet);
						HiBoostDataSet_Test.InitBicExampleList(strTemp);
						bds_Test.SetRealDataSet(&HiBoostDataSet_Test);
						bds_Test.SetTargetLabel(+1);
						TestExampleList.myInit(&bds_Test);

						for ( i = 0; i < TrainExampleList.PosList.ExampleAmount; ++i ) TrainExampleList.PosList.rgExample[i].Weight = 1.0; // 1.0 / TrainExampleList.PosList.ExampleAmount;
						for ( i = 0; i < TrainExampleList.NegList.ExampleAmount; ++i ) TrainExampleList.NegList.rgExample[i].Weight = 1.0; // 1e4 / TrainExampleList.NegList.ExampleAmount; // 1.0;
						TrainExampleList.NormalizeExampleWeight();
						for ( i = 0; i < TestExampleList.PosList.ExampleAmount; ++i ) TestExampleList.PosList.rgExample[i].Weight = 1.0; // 1.0 / TestExampleList.PosList.ExampleAmount;
						for ( i = 0; i < TestExampleList.NegList.ExampleAmount; ++i ) TestExampleList.NegList.rgExample[i].Weight = 1.0; // 1e4 / TestExampleList.NegList.NodeAmount; // 1.0;
						TestExampleList.NormalizeExampleWeight();

						CascadeConfig.strPN_ForTrain = GlobalHiBoostSettings.GetPN_BoostModel(i_node);

						system("cls");
						GlobalHiBoostSettings.MakeFN_BoostTrainLog(strTemp, i_node);
						ofstream outTrainLog(strTemp);
						CCascadedAdaBoostClassifier& cabc = cabcList.pElement[i_node];
						GlobalHiBoostSettings.MakeFN_BoostModel(strTemp, i_node);
						cabc.LoadFromFile(strTemp);
						cabc.Train(
							strTemp, Cascade_StartTrainingLayer, 0,
							&bds_Train, TrainExampleList,
							&bds_Test, TestExampleList,
							CascadeConfig,
							outTrainLog);
						outTrainLog.clear();
						outTrainLog.close();
					} // (Op_BoostTrainTest & 1)

					if (Op_BoostTrainTest & 2)
					{
						CCascadedAdaBoostClassifier& cabc = cabcList.pElement[i_node];
						CBinaryClassifier* pBC = &cabc;

						GlobalHiBoostSettings.MakeFN_BoostModel(strTemp, i_node);
						ifstream inFile_Model(strTemp);
						cabc.InputFromStream(inFile_Model);
						inFile_Model.clear();
						inFile_Model.close();

						sgnImageSet = 1;

						int Amount_Pos_File = GlobalHiBoostSettings.GetAmount_GT_Annotation(sgnImageSet);
						int Amount_Neg_File = GlobalHiBoostSettings.GetAmount_SrcImage(sgnImageSet, 0);

						CHiBoostNodeSetAppearanceIPFE nsa;
						CImagePyramidPositionFeatureExtractor* pIPPFE = new CImagePyramidPositionFeatureExtractor(nsa.GetNodeAppearnceIPFE(i_node)->myClone(), 1);

						CImg<int> imgSrc;
						CBicExample tBicExample;
						CImagePyramidPosition ipp;
						double tConfidence;
						int tPrediction = 0;

						CBinaryClassificationResult_ByConfidence bcr;
						bcr.Clear();

						class CTPE
						{
						public:
							int index;
							double score;
						public:
							bool operator < (const CTPE& AnotherInstance) const { return score > AnotherInstance.score; }
						};
						CSimpleTypeArray<double> cpsl;
						cpsl.Resize(Amount_Pos_File);
						CTPE tpe;
						CSimpleTypeArray<CTPE> pel;
						pel.Clear();

						string strPosSort = "PosSort\\";
						CExternalTools::ConsoleTools::MakeDirectory(strPosSort);

						int LAYER_DISPLAY_WIDTH = 100;
						int CONFIDENCE_BIN_AMOUNT = 600;
						sprintf_s(strTemp, "%sCascadeConfidence.%s.txt",
							GlobalHiBoostSettings.GetPN_BoostModel(i_node).c_str(),
							GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet));
						ofstream outFile_CC(strTemp);
						CSimpleTypeArray<double> cc_list;
						CSimpleTypeArray<double> cmin_list;
						CSimpleTypeArray<double> cmax_list;
						CSimpleTypeArray<CSimpleTypeArray<double>> mat_cc_Pos;
						CSimpleTypeArray<CSimpleTypeArray<double>> mat_cc_Neg;
						cmin_list.Clear();
						cmax_list.Clear();
						mat_cc_Pos.Clear();
						mat_cc_Neg.Clear();

						for ( i = 0; i < Amount_Pos_File; ++i )
						{
							GlobalHiBoostSettings.MakeFN_CropGT(strTemp, i_node, sgnImageSet, i);
							CExternalTools::myLoadImage(strTemp, imgSrc);
							pIPPFE->SetImage(imgSrc, "");

							CurrentBicExampleConfigCopy.BuildPosExample(tBicExample, -1, -1);
							tBicExample.ToIpp(ipp);
							pIPPFE->SetQuery(ipp);

							// Pos
							int el;
							cabc.Classify(pIPPFE, 0, -1, el, cc_list);
							mat_cc_Pos.PushBack(cc_list);
							outFile_CC<<"1\t"<<el;
							for ( int jj = 0; jj < el; ++jj )
							{
								tConfidence = cc_list.pElement[jj];

								if (jj >= (int)cmin_list.Size)
									cmin_list.PushBack(tConfidence);
								else if (cmin_list.pElement[jj] > tConfidence)
									cmin_list.pElement[jj] = tConfidence;
								if (jj >= (int)cmax_list.Size)
									cmax_list.PushBack(tConfidence);
								else if (cmax_list.pElement[jj] < tConfidence)
									cmax_list.pElement[jj] = tConfidence;
								sprintf_s(strTemp,"\t%+.6lf", tConfidence);

								outFile_CC<<strTemp;
							}
							outFile_CC<<endl;

							pBC->Classify(pIPPFE, tConfidence, tPrediction);
							bcr.Pos.PushBack(tConfidence);

							cpsl.pElement[i/2*4+1-i] = tConfidence;
							tpe.index = i;
							tpe.score = tConfidence;
							pel.PushBack(tpe);

							sprintf_s(strTemp, "Test pos set %d/%d...", i+1, Amount_Pos_File);
							CExternalTools::ConsoleTools::ClearCurrentLine();
							cout<<strTemp;
						}
						bcr.Analyse();

						sort(pel.Begin(), pel.End());
						for ( i = 0; i < Amount_Pos_File; ++i )
						{
							tpe = pel.pElement[i];
							GlobalHiBoostSettings.MakeFN_CropGT(strTemp, i_node, sgnImageSet, i);
							CExternalTools::myLoadImage(strTemp, imgSrc);
							//CExternalTools::myLoadImage(pPosMaterialFileNameSet->pElement[tpe.index], imgSrc);
							CImg<int> imgOutput;
							imgOutput = imgSrc;
							sprintf_s(strTemp, "%.3lf / %.3lf", tpe.score, cpsl.pElement[tpe.index]);
							CExternalTools::OutputTextToImage(imgOutput, strTemp, 0, 0, 255, 255, 255, 255, 0, 0);
							sprintf_s(strTemp, "%04d", tpe.index);
							CExternalTools::OutputTextToImage(imgOutput, strTemp, 0, imgOutput.height-10, 255, 255, 255, 255, 0, 0);
							sprintf_s(strTemp, "%s%s.%04d.jpg", strPosSort.c_str(), GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet), i);
							CExternalTools::mySaveImage(strTemp, imgOutput);
						}
						//return 0;

						CSimpleTypeArray<CBicExample> BicExampleList;
						//CSimpleTypeArray<CHiBoostExample> ExampleList;
						//const CHiBoostExample* qte;
						int tLayerExampleAmount;
						int sImageExampleAmount;

						CTimer tTimer;
						tTimer.Reset();

						for ( i = 0; i < Amount_Neg_File; ++i )
						{
							GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, 0, i);
							CExternalTools::myLoadImage(strTemp, imgSrc);
							pIPPFE->SetImage(imgSrc, "");

							BicExampleList.Clear();
							sImageExampleAmount = 0;
							for ( j = 0; ; ++j )
							{
								tLayerExampleAmount = CurrentBicExampleConfigCopy.GenerateNegExampleList(BicExampleList, true, imgSrc.width, imgSrc.height,
									Scan_PixelSampleMargin_ForDetect, Scan_PixelSampleRate_ForDetect, j, Scan_ScaleFactor_ForDetect,
									-1, -1);
								if (tLayerExampleAmount < 1) break;
								sImageExampleAmount += tLayerExampleAmount;
							}

							tTimer.Start();

							for ( j = 0; j < (int)BicExampleList.Size; ++j )
							{
								BicExampleList.pElement[j].ToIpp(ipp);
								pIPPFE->SetQuery(ipp);

								// Neg
								int el;
								cabc.Classify(pIPPFE, 0, -1, el, cc_list);
								mat_cc_Neg.PushBack(cc_list);
								outFile_CC<<"0\t"<<el;
								for ( int jj = 0; jj < el; ++jj )
								{
									tConfidence = cc_list.pElement[jj];

									if (jj >= (int)cmin_list.Size)
										cmin_list.PushBack(tConfidence);
									else if (cmin_list.pElement[jj] > tConfidence)
										cmin_list.pElement[jj] = tConfidence;
									if (jj >= (int)cmax_list.Size)
										cmax_list.PushBack(tConfidence);
									else if (cmax_list.pElement[jj] < tConfidence)
										cmax_list.pElement[jj] = tConfidence;
									sprintf_s(strTemp,"\t%+.6lf", tConfidence);

									outFile_CC<<strTemp;
								}
								outFile_CC<<endl;

								pBC->Classify(pIPPFE, tConfidence, tPrediction);
								bcr.Neg.PushBack(tConfidence);

								//if (tConfidence > DrawThreshold) continue;

								//++Amount_FalseAlarm;
								//HiBoostExampleConfig.GetStdPartContextSize(iBox.w, iBox.h, i_node);
								//dBox.w = iBox.w / qte->layer_scale_x;
								//dBox.h = iBox.h / qte->layer_scale_y;
								//dBox.x = qte->real_x - dBox.w * 0.5;
								//dBox.y = qte->real_y - dBox.h * 0.5;
								//iBox.myInit(dBox);
								//CExternalTools::OutputRectBoxToImage(imgOutput, iBox, 255, 0, 0);
							}
							bcr.Analyse();

							tTimer.Stop();

							double TargetFPR = 1e-4;
							double MR = 1.0 - bcr.Get_Recall_By_FalsePositiveRate(TargetFPR);

							sprintf_s(strTemp, "Node %02d, Test neg set %d/%d: %.1lf/%.0lf kw, MR%.0lf = %.3lf, %.2lf spi, %.2lf kwps",
								i_node, i+1, Amount_Neg_File, sImageExampleAmount/1000.0, (double)bcr.Neg.Size/1000.0,
								log(TargetFPR)/log(10.0), MR, tTimer.GetCumulativeTime() / (i+1), bcr.Neg.Size / tTimer.GetCumulativeTime() / 1000.0
								);
							CExternalTools::ConsoleTools::ClearCurrentLine();
							cout<<strTemp;
							if (i==Amount_Neg_File-1)
							{
								cout<<endl;
								outLog<<strTemp<<endl;
							}
						}

						outFile_CC.clear();
						outFile_CC.close();

						size_t lvl_amount = (int)cmax_list.Size;
						cc_list.Resize(CONFIDENCE_BIN_AMOUNT); cc_list.Fill(0.0);
						CSimpleTypeArray<CSimpleTypeArray<double>> cc_hist_Pos;
						CSimpleTypeArray<CSimpleTypeArray<double>> cc_hist_Neg;
						cc_hist_Pos.Resize(lvl_amount); cc_hist_Pos.Fill(cc_list);
						cc_hist_Neg.Resize(lvl_amount); cc_hist_Neg.Fill(cc_list);
						double base_cmin, base_cmax;
						base_cmin = cmin_list.pElement[0]; base_cmax = cmax_list.pElement[0];
						for ( size_t jjj = 0; jjj < lvl_amount; ++jjj )
						{
							if (base_cmin > cmin_list.pElement[jjj]) base_cmin = cmin_list.pElement[jjj];
							if (base_cmax < cmax_list.pElement[jjj]) base_cmax = cmax_list.pElement[jjj];
							cmax_list.pElement[jjj] = (cmax_list.pElement[jjj] - cmin_list.pElement[jjj]) / CONFIDENCE_BIN_AMOUNT;
						}
						base_cmax = (base_cmax - base_cmin) / CONFIDENCE_BIN_AMOUNT;

						// Pos
						for ( size_t iii = 0; iii < mat_cc_Pos.Size; ++iii )
						{
							CSimpleTypeArray<double>& ccl = mat_cc_Pos.pElement[iii];
							for ( size_t jjj = 0; jjj < ccl.Size; ++jjj )
							{
								tConfidence = (ccl.pElement[jjj] - base_cmin) / base_cmax;
								//tConfidence = (ccl.pElement[jjj] - cmin_list.pElement[jjj]) / cmax_list.pElement[jjj];
								tPrediction = CMyMath::TranslateNumber_Round(tConfidence, (int)0);
								tPrediction = (tPrediction<0 ? 0 : (tPrediction>=CONFIDENCE_BIN_AMOUNT ? CONFIDENCE_BIN_AMOUNT-1 : tPrediction));
								cc_hist_Pos.pElement[jjj].pElement[tPrediction] += 1.0;
							}
						}
						for ( size_t jjj = 0; jjj < lvl_amount; ++jjj )
						{
							CSimpleTypeArray<double>& cch = cc_hist_Pos.pElement[jjj];
							tConfidence = EPS;
							for ( int ooo = 0; ooo < CONFIDENCE_BIN_AMOUNT; ++ooo )
								if (cch.pElement[ooo] > tConfidence) tConfidence = cch.pElement[ooo];
							for ( int ooo = 0; ooo < CONFIDENCE_BIN_AMOUNT; ++ooo )
								cch.pElement[ooo] /= tConfidence;
						}
						// Neg
						for ( size_t iii = 0; iii < mat_cc_Neg.Size; ++iii )
						{
							CSimpleTypeArray<double>& ccl = mat_cc_Neg.pElement[iii];
							for ( size_t jjj = 0; jjj < ccl.Size; ++jjj )
							{
								tConfidence = (ccl.pElement[jjj] - base_cmin) / base_cmax;
								//tConfidence = (ccl.pElement[jjj] - cmin_list.pElement[jjj]) / cmax_list.pElement[jjj];
								tPrediction = CMyMath::TranslateNumber_Round(tConfidence, (int)0);
								tPrediction = (tPrediction<0 ? 0 : (tPrediction>=CONFIDENCE_BIN_AMOUNT ? CONFIDENCE_BIN_AMOUNT-1 : tPrediction));
								cc_hist_Neg.pElement[jjj].pElement[tPrediction] += 1.0;
							}
						}
						for ( size_t jjj = 0; jjj < lvl_amount; ++jjj )
						{
							CSimpleTypeArray<double>& cch = cc_hist_Neg.pElement[jjj];
							tConfidence = EPS;
							for ( int ooo = 0; ooo < CONFIDENCE_BIN_AMOUNT; ++ooo )
								if (cch.pElement[ooo] > tConfidence) tConfidence = cch.pElement[ooo];
							for ( int ooo = 0; ooo < CONFIDENCE_BIN_AMOUNT; ++ooo )
								cch.pElement[ooo] /= tConfidence;
						}
						CImg<int> imgCHD;
						imgCHD.assign(LAYER_DISPLAY_WIDTH*(int)lvl_amount, CONFIDENCE_BIN_AMOUNT, 1, 3);
						for ( int iiy = 0; iiy < (int)imgCHD.height; ++iiy )
						{
							for ( int iix = 0; iix < (int)imgCHD.width; ++iix )
							{
								if (iix%LAYER_DISPLAY_WIDTH==0 && iix>0)
								{
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 0) = 0;
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 1) = 0;
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 2) = 0;
									continue;
								}

								tConfidence = (cabc.rgLayer[iix/LAYER_DISPLAY_WIDTH].CascadeThreshold - base_cmin) / base_cmax;
								tPrediction = CMyMath::TranslateNumber_Round(tConfidence, (int)0);
								tPrediction = (tPrediction<0 ? 0 : (tPrediction>=CONFIDENCE_BIN_AMOUNT ? CONFIDENCE_BIN_AMOUNT-1 : tPrediction));
								if (abs(tPrediction-iiy) < 2)
								{
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 0) = 0;
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 1) = 0;
									imgCHD.at(iix, imgCHD.height-1-iiy, 0, 2) = 0;
									continue;
								}

								tConfidence = cc_hist_Pos.pElement[iix/LAYER_DISPLAY_WIDTH].pElement[iiy];
								tPrediction = CMyMath::TranslateNumber_Round(tConfidence * 255.0, (int)0);
								tPrediction = (tPrediction<0 ? 0 : (tPrediction>255 ? 255 : tPrediction));
								imgCHD.at(iix, imgCHD.height-1-iiy, 0, 0) = 255 - tPrediction;

								tConfidence = cc_hist_Neg.pElement[iix/LAYER_DISPLAY_WIDTH].pElement[iiy];
								tPrediction = CMyMath::TranslateNumber_Round(tConfidence * 255.0, (int)0);
								tPrediction = (tPrediction<0 ? 0 : (tPrediction>255 ? 255 : tPrediction));
								imgCHD.at(iix, imgCHD.height-1-iiy, 0, 1) = 255 - tPrediction;

								imgCHD.at(iix, imgCHD.height-1-iiy, 0, 2) = 255;
							}
						}
						//imgCHD.display();
						sprintf_s(strTemp, "%sBoostConfidenceHistogram.jpg", GlobalHiBoostSettings.GetPN_BoostModel(i_node).c_str());
						CExternalTools::mySaveImage(strTemp, imgCHD);

						sprintf_s(strTemp, "Test MR-4 = %.4lf;", 1.0 - bcr.Get_Recall_By_FalsePositiveRate(1e-4));
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;
						sprintf_s(strTemp, "Test MR-3 = %.4lf;", 1.0 - bcr.Get_Recall_By_FalsePositiveRate(1e-3));
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;
						sprintf_s(strTemp, "Test MR-2 = %.4lf;", 1.0 - bcr.Get_Recall_By_FalsePositiveRate(1e-2));
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;
						sprintf_s(strTemp, "Test MR-1 = %.4lf;", 1.0 - bcr.Get_Recall_By_FalsePositiveRate(1e-1));
						cout<<strTemp<<endl;
						outLog<<strTemp<<endl;

						GlobalHiBoostSettings.MakeFN_BoostTestROC(strTemp, i_node);
						ofstream outROC(strTemp);
						bcr.OutputROCtoStream(outROC, 120, 1e-6, 1e-0, true);
						outROC.clear();
						outROC.close();

						cout<<endl;
						outLog<<endl;

						CDataStructureTools::MyRelease_Single(pIPPFE);

					} // (Op_BoostTrainTest & 2)
				} // i_node
			} // (Op_BoostTrainTest & 3)

			if (Op_TrainPerceptronModel & 1)
			{
				CSimpleTypeArray<InstanceTreeType> InstTreeList;

				CProposalTree ProposalTree;
				ProposalTree.ReadAndOrTreeModel(strFN_Perceptron_InitializedModel);
				if (TargetNodeIndex>=0 && TargetNodeIndex<AbstractTree.NodeAmount)
					ProposalTree.model.Root = TargetNodeIndex;
				ProposalTree.PrepareModel();

				ProposalTree.ParseGroundTruthList(InstTreeList, GT_List_Train, true, "", strPN_Perceptron_GT_Instance_Train, strPN_Perceptron_GT_Image_Train);
				//ProposalTree.ParseGroundTruthList(InstTreeList, GT_List_Test, true, "", strPN_Perceptron_GT_Instance_Test, strPN_Perceptron_GT_Image_Test);
			} // (Op_TrainPerceptronModel & 1)

			if (Op_TrainPerceptronModel & 2)
			{
				CProposalTree ProposalTree;

				ProposalTree.ReadAndOrTreeModel(strFN_Perceptron_InitializedModel);
				if (TargetNodeIndex>=0 && TargetNodeIndex<AbstractTree.NodeAmount)
					ProposalTree.model.Root = TargetNodeIndex;
				ProposalTree.PrepareModel();

				CExternalTools::ConsoleTools::MakeDirectory(strPN_Perceptron_TrainedModel);
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Perceptron_ImageCache);

				int ii = GlobalHiBoostSettings.GetAmount_SrcImage(0, 0);
				CSimpleTypeArray<string> List_strFN_SrcImage_Train_Neg;
				List_strFN_SrcImage_Train_Neg.Resize(ii);
				CSimpleTypeArray<string> List_strSrcImageHashName_Train_Neg;
				List_strSrcImageHashName_Train_Neg.Resize(ii);
				for ( i_image = 0; i_image < ii; ++i_image )
				{
					GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, 0, 0, i_image);
					List_strFN_SrcImage_Train_Neg.pElement[i_image] = strTemp;
					List_strSrcImageHashName_Train_Neg.pElement[i_image] = GlobalHiBoostSettings.GetPerceptronImageHashName(0, 0, i_image);
				}

				ProposalTree.LearnModelParamaters(
					GT_List_Train,
					strPN_Perceptron_ParseLog_Train, strPN_Perceptron_TrainedModel,
					strPN_Perceptron_GT_Instance_Train,
					List_strFN_SrcImage_Train_Neg,
					List_strSrcImageHashName_Train_Neg);
			} // (Op_TrainPerceptronModel & 2)

			if (Op_BoostDetect & 3)
			{
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Base_BoostDetect);

				CProposalTree ProposalTree;
				ProposalTree.ReadAndOrTreeModel(strFN_Perceptron_InitializedModel);
				ProposalTree.PrepareModel();

				CHiBoostNodeSetAppearanceIPFE nsa;
				CImagePyramidPositionFeatureExtractor* pIPPFE = new CImagePyramidPositionFeatureExtractor(nsa.GetNodeAppearnceIPFE(0)->myClone(), 1);

				CSimpleTypeArray<double> TargetConfidenceThresholdList;
				TargetConfidenceThresholdList.Resize(AbstractTree.NodeAmount);
				TargetConfidenceThresholdList.Fill(-1e20);

				//cabcList.DeepClear(); cabcList.Resize(AbstractTree.NodeAmount);
				for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
				{
					if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;
					if (TargetNodeIndex<0 && !fNodeSelectedList.pElement[i_node]) continue;

					GlobalHiBoostSettings.MakeFN_BoostModel(strTemp, i_node);
					cabcList.pElement[i_node].LoadFromFile(strTemp);

					GlobalHiBoostSettings.MakeFN_BoostTestROC(strTemp, i_node);
					ifstream inFile(strTemp);
					int ni;
					double t1, t2, t3, t4;
					if ((inFile>>ni>>t1>>t2) && (ni>0) && !(t1>BoostDetect_TargetFPR) && !(t2<BoostDetect_TargetFPR))
					{
						double& TargetCT = TargetConfidenceThresholdList.pElement[i_node];
						for ( ; ni >= 0; --ni )
						{
							inFile>>t1>>t2>>t3>>t4; // FPR, DR, CT, 1-DR
							if (t1+EPS>BoostDetect_TargetFPR)
							{
								TargetCT = t3;
								sprintf_s(strTemp, "Node.%02d Detect: FPR = %8.4lf%%, DR = %6.2lf%%, CT = %.6lf", i_node, t1*100.0, t2*100.0, t3);
								cout<<strTemp<<endl;
								outLog<<strTemp<<endl;
								break;
							}
						}
					}
					inFile.clear();
					inFile.close();

					CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.GetPN_BoostDetect_SingleNode(i_node));
				}

				CBicDetector::CLayerResult LayerResult;
				CBicDetector BicDetector;
				BicDetector.Init_IPPFE_and_Classifier(pIPPFE, NULL);
				BicDetector.SetConfidenceThreshold(-1e20);
				BicDetector.Scan_SampleMargin	=	Scan_PixelSampleMargin_ForDetect;
				BicDetector.Scan_SampleRate		=	Scan_PixelSampleRate_ForDetect;
				BicDetector.Scan_ScalingFactor	=	Scan_ScaleFactor_ForDetect;
				BicDetector.MeanShiftConfig.KernelConfig.dx = BicDetector.Scan_SampleMargin + 1.0;
				BicDetector.MeanShiftConfig.KernelConfig.dy = BicDetector.Scan_SampleMargin + 1.0;
				BicDetector.MeanShiftConfig.KernelConfig.dw = 1.3;
				BicDetector.MeanShiftConfig.KernelConfig.dw = 1.3;

				for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
				{
					if (sgnImageSet==0 && !(Flag_Detect_ImageSet & 1)) continue;
					if (sgnImageSet==1 && !(Flag_Detect_ImageSet & 2)) continue;

					const CHiBoostGroundTruthList* pCurrent_GT_List;
					if (sgnImageSet == 0) pCurrent_GT_List = &GT_List_Train;
					if (sgnImageSet == 1) pCurrent_GT_List = &GT_List_Test;
					int i_pGT = 0;

					CTimer timDetect;
					timDetect.Reset();
					int count_image = 0;

					CSimpleTypeArray<CBinaryClassificationResult_ByConfidence> bcrcList;
					bcrcList.Resize(AbstractTree.NodeAmount);
					CSimpleTypeArray<CSimpleTypeArray<CImg<double>>> matImgDoubleForOutput;
					matImgDoubleForOutput.Resize(AbstractTree.NodeAmount);
					for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
					{
						bcrcList.pElement[i_node].Clear();
						CSimpleTypeArray<CImg<double>>& List_ImgDoubleForOutput = matImgDoubleForOutput.pElement[i_node];
						List_ImgDoubleForOutput.Resize(100); List_ImgDoubleForOutput.Clear();
					}

					for ( sgnPosNeg = 1; sgnPosNeg >= 0; --sgnPosNeg )
					//for ( sgnPosNeg = 0; sgnPosNeg < 2; ++sgnPosNeg )
					{
						if (sgnPosNeg==1 && !(Flag_Detect_PosNeg & 1)) continue;
						if (sgnPosNeg==0 && !(Flag_Detect_PosNeg & 2)) continue;

						int Amount_SrcImage = GlobalHiBoostSettings.GetAmount_SrcImage(sgnImageSet, sgnPosNeg);
						for ( i_image = 0; i_image < Amount_SrcImage; ++i_image )
						{
							CImg<int> imgSrc;
							GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, sgnPosNeg, i_image);
							CExternalTools::myLoadImage(strTemp, imgSrc);
							++count_image;

							CSimpleTypeArray<CDetectionWithScore> MyDetList;
							CDetectionWithScore tDetetionWithScore;
							CSimpleTypeArray<CSimpleTypeArray<CCandidateDetection>> matCanDet;
							matCanDet.Resize(AbstractTree.NodeAmount);
							CSimpleTypeArray<CSimpleTypeArray<CDetectionWithScore>> matGtDet;
							matGtDet.Resize(AbstractTree.NodeAmount);
							for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
							{
								matCanDet.pElement[i_node].Clear();
								matGtDet.pElement[i_node].Clear();
							}

							if (sgnPosNeg == 1)
							{
								CHiBoostImageEntity iEntity;
								CHiBoostGroundTruth iGT;
								InstanceTreeType iTree;
								CMyTreeInstance iMTI;
								CRectBox<double> dBox;

								iEntity.SetImage(imgSrc, "", false);
								for ( ; i_pGT < pCurrent_GT_List->Amount_GroundTruth; ++i_pGT )
								{
									iGT = pCurrent_GT_List->GroundTruthList.pElement[i_pGT];
									if (iGT.MaterialIndex < i_image) continue;
									if (iGT.MaterialIndex > i_image) break;
									if (iGT.fIsFlipped) continue;

									iEntity.ReadParsedLeafInstances(&iGT);
									ProposalTree.ParseEntityGroundTruth(iTree, iEntity, false);
									ProposalTree.MakeMyTreeInstance(iMTI, iTree, 0, iEntity);

									for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
									{
										CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[i_node];

										const CBicExampleConfig& BicEC = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);
										BicEC.MakeTightBoxFromCenterAndIplScale(dBox, tMNI.x, tMNI.y, 1.0/tMNI.scale);
										tDetetionWithScore.Detection = dBox;
										tDetetionWithScore.fIsMatched = false;
										tDetetionWithScore.Score = 0.0;
										matGtDet.pElement[i_node].PushBack(tDetetionWithScore);
									}
								}
							}

							CSimpleTypeArray<CRectBox<int>> GtBoxList;
							if (sgnPosNeg == 1)
							{
								GlobalHiBoostSettings.MakeFN_INRIA_Annotation(strTemp, sgnImageSet, i_image);
								CGroundTruthReader_INRIA::ReadGroundTruthFile(GtBoxList, strTemp);
							}
							else
								GtBoxList.Clear();

							BicDetector.SetImage(imgSrc);
							const CZoomableImage& ZoomImage_SrcImage = pIPPFE->ZoomImage;
							CZoomConfig ZoomConfig_SrcImage;

							CImg<int> imgDetect;
							CImg<int> imgOutput;
							CImg<int> imgTempInt;
							CImg<double> imgTempDouble;

							timDetect.Start();

							CSimpleTypeArray<bool> fNodeExitList;
							fNodeExitList.Resize(AbstractTree.NodeAmount);
							fNodeExitList.Fill(false);
							int ExitCount = 0;

							for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
							{
								CSimpleTypeArray<CImg<double>>& List_ImgDoubleForOutput = matImgDoubleForOutput.pElement[i_node];
								List_ImgDoubleForOutput.Clear();
							}
							double OutputScale_1 = 1.0;
							double OutputScale_2 = 1.0 / 3.0;
							int Output_W_2 = CMyMath::TranslateNumber_Round(imgSrc.width * OutputScale_2, (int)0);
							int Output_H_2 = CMyMath::TranslateNumber_Round(imgSrc.height * OutputScale_2, (int)0);

							for ( i_layer = 0; ; ++i_layer )
							{
								if (ExitCount >= AbstractTree.NodeAmount) break;
								for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
								{
									if (fNodeExitList.pElement[i_node]) continue;

									if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex)
									{ ++ExitCount; fNodeExitList.pElement[i_node] = true; continue; }
									if (TargetNodeIndex<0 && !fNodeSelectedList.pElement[i_node])
									{ ++ExitCount; fNodeExitList.pElement[i_node] = true; continue; }

									nsa.GetNodeAppearnceIPFE(i_node);
									pIPPFE->RecomputeFeatureDimension();
									BicDetector.pImagePatchClassifier = cabcList.pElement + i_node;
									BicDetector.BicExampleConfig = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);
									BicDetector.BicExampleConfig.SetScanningFitBoxConfiguration(CBicExampleConfig::FIT_BOX_STYLE_MIN_SIZE, 64, 128);
									BicDetector.SetConfidenceThreshold(TargetConfidenceThresholdList.pElement[i_node]);
									int qq = BicDetector.ProcessImageLayer(LayerResult, i_layer, true);

									if (qq < 1)
									{ ++ExitCount; fNodeExitList.pElement[i_node] = true; continue; }

									if (Op_BoostDetect & 1)
									{
										matCanDet.pElement[i_node].PushBack(LayerResult.CanDetList);
									}

									if (Op_BoostDetect & 2)
									{
										CZoomableImage zi;
										zi.myInit(LayerResult.imgConfidence);
										CZoomConfig zc;
										zc.myInit(sqrt(1.0 * (Output_W_2 * Output_H_2) / (LayerResult.LW * LayerResult.LH)));
										zi.BuildImage(imgTempDouble, Output_W_2, Output_H_2, zc, CDenseImage::EXPANDING_MODE_EDGE);
										for ( int iy = 0; iy < (int)imgTempDouble.height; ++iy ) for ( int ix = 0; ix < (int)imgTempDouble.width; ++ix )
										{
											double t = imgTempDouble.at(ix, iy);
											//t = exp(t);
											imgTempDouble.at(ix, iy) = t;
										}
										CSimpleTypeArray<CImg<double>>& List_ImgDoubleForOutput = matImgDoubleForOutput.pElement[i_node];
										List_ImgDoubleForOutput.PushBack(imgTempDouble);
									}
								} // i_node
							} // i_layer

							timDetect.Stop();

							int ix, iy;
							CRectBox<double> dBox;
							double i_vmin, i_vmax;
							double global_vmin, global_vmax;

							for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
							{
								if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;
								if (TargetNodeIndex<0 && !fNodeSelectedList.pElement[i_node]) continue;

								const CBicExampleConfig& CurrentBicExampleConfig = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(i_node);

								if (Op_BoostDetect & 1)
								{
									BicDetector.BicExampleConfig = CurrentBicExampleConfig;
									BicDetector.SetConfidenceThreshold(TargetConfidenceThresholdList.pElement[i_node]);
									BicDetector.DoNMS(MyDetList, matCanDet.pElement[i_node], true);
									
									CSimpleTypeArray<CDetectionWithScore>& cur_gt_list = matGtDet.pElement[i_node];

									CBinaryClassificationResult_ByConfidence& cur_bcrc = bcrcList.pElement[i_node];
									cur_bcrc.ExtraFalseNegAmount += CDetectionWithScore::CheckDetections(MyDetList, cur_gt_list);

									ZoomConfig_SrcImage = ZoomImage_SrcImage.BuildImage(imgOutput, OutputScale_1, OutputScale_1, CDenseImage::EXPANDING_MODE_EDGE);
									int _color;

									for ( int i_gt = 0; i_gt < (int)cur_gt_list.Size; ++i_gt )
									{
										ZoomConfig_SrcImage.WorkOnBox(dBox, cur_gt_list.pElement[i_gt].Detection);
										_color = 0x00ffff00;
										CExternalTools::DrawRectBox(imgOutput, dBox, _color);
									}
									for ( int i_det = 0; i_det < (int)MyDetList.Size; ++i_det )
									{
										tDetetionWithScore = MyDetList.pElement[i_det];
										(tDetetionWithScore.fIsMatched ? cur_bcrc.Pos : cur_bcrc.Neg).PushBack(tDetetionWithScore.Score);

										ZoomConfig_SrcImage.WorkOnBox(dBox, tDetetionWithScore.Detection);
										_color = (tDetetionWithScore.fIsMatched ? 0x0000ff00 : 0x00ff0000);
										CExternalTools::DrawRectBox(imgOutput, dBox, _color);

										sprintf_s(strTemp, "%+.4lf", tDetetionWithScore.Score); // 0.0 - log(exp(0.0 - tDetetionWithScore.Score) - 1.0));
										CExternalTools::OutputTextToImage(imgOutput, strTemp,
											(int)dBox.x, (int)dBox.y,
											((_color>>16)&255), ((_color>>8)&255), ((_color>>0)&255),
											0, 0, 0);
									}

									cur_bcrc.Analyse();
									double CurrentAP = cur_bcrc.Get_AveragePrecision();

									sprintf_s(strTemp, "Current AP = %.2lf%%", CurrentAP * 100.0);
									CExternalTools::OutputTextToImage(imgOutput, strTemp, 0, 0, 255, 255, 255, 0, 0, 0);

									sprintf_s(strTemp, "%sDetection.%s.%s.%04d.jpg",
										GlobalHiBoostSettings.GetPN_BoostDetect_SingleNode(i_node).c_str(),
										GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
										GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
										i_image);
									CExternalTools::mySaveImage(strTemp, imgOutput);

									sprintf_s(strTemp, "%s %s %04d / %04d; [%s per image]; Node.%02d AP = %.2lf%%;",
										GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
										GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
										i_image, Amount_SrcImage,
										CExternalTools::GetTimeText(timDetect.GetCumulativeTime() / count_image),
										i_node, CurrentAP * 100.0);
									CExternalTools::ConsoleTools::ClearCurrentLine();
									cout<<strTemp;
									outLog<<strTemp<<endl;
								}

								if (Op_BoostDetect & 2)
								{
									CSimpleTypeArray<CImg<double>>& List_ImgDoubleForOutput = matImgDoubleForOutput.pElement[i_node];

									int ncol = CMyMath::TranslateNumber_Round(sqrt((1.0 + List_ImgDoubleForOutput.Size) / Output_W_2 * Output_H_2), (int)0);
									if (ncol < 1) ncol = 1;
									int nrow = (((int)List_ImgDoubleForOutput.Size + ncol) / ncol);

									global_vmin = 0.0;
									global_vmax = 1.0;

									imgTempDouble.assign(Output_W_2 * ncol, Output_H_2 * nrow);
									imgTempDouble.fill(0.0);
									int i_output;
									for ( i_output = 0; i_output <= (int)List_ImgDoubleForOutput.Size; ++i_output )
									{
										int i_temp = (i_output>0 ? i_output : 1) - 1;
										imgTempDouble.draw_image(
											List_ImgDoubleForOutput.pElement[i_temp],
											Output_W_2 * (i_output % ncol), Output_H_2 * (i_output / ncol));
									}

									i_vmax = imgTempDouble.maxmin(i_vmin);
									//i_vmin = global_vmin;
									//i_vmax = global_vmax;

									CExternalTools::NormalizeToGeneralIntGrayscaleImage(imgTempDouble, imgTempInt, i_vmin, i_vmax);

									ZoomConfig_SrcImage.myInit(OutputScale_2);
									ZoomImage_SrcImage.BuildImage(imgDetect, Output_W_2, Output_H_2, ZoomConfig_SrcImage, CDenseImage::EXPANDING_MODE_EDGE);

									imgOutput.assign(Output_W_2 * ncol, Output_H_2 * nrow, 1, 3);
									imgOutput.fill(0);
									imgOutput.draw_image(imgTempInt, 0, 0, 0, 0);
									imgOutput.draw_image(imgTempInt, 0, 0, 0, 1);
									imgOutput.draw_image(imgTempInt, 0, 0, 0, 2);
									imgOutput.draw_image(imgDetect, 0, 0);

									for ( ix = 1; ix < ncol; ++ix )
										imgOutput.draw_line(Output_W_2 * ix, 0, Output_W_2 * ix, Output_H_2 * nrow - 1, CExternalTools::GetIntArrayRGB(255, 0, 0));
									for ( iy = 1; iy < nrow; ++iy )
										imgOutput.draw_line(0, Output_H_2 * iy, Output_W_2 * ncol - 1, Output_H_2 * iy, CExternalTools::GetIntArrayRGB(255, 0, 0));

									for ( i_output = 0; i_output <= (int)List_ImgDoubleForOutput.Size; ++i_output )
									{
										int i_temp = (i_output>0 ? i_output : 1) - 1;

										for ( int i_gt = 0; i_gt < (int)GtBoxList.Size; ++i_gt )
										{
											dBox.myInit(GtBoxList.pElement[i_gt]);
											ZoomConfig_SrcImage.WorkOnBox(dBox, dBox);
											dBox.x += Output_W_2 * (i_output % ncol);
											dBox.y += Output_H_2 * (i_output / ncol);
											CExternalTools::DrawRectBox(imgOutput, dBox, 255, 255, 0);
										}

										if (i_output > 0)
										{
											GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(0).
												//CurrentBicExampleConfig.
												MakeTightBoxFromCenterAndIplScale(dBox,
												Output_W_2 * (i_output % ncol + 0.5),
												Output_H_2 * (i_output / ncol + 0.5),
												pow(Scan_ScaleFactor_ForDetect, -i_temp) / OutputScale_2);
											CExternalTools::DrawRectBox(imgOutput, dBox, 0, 255, 0);
										}
									}

									sprintf_s(strTemp, " [%.3lf, %.3lf] ", i_vmin, i_vmax);
									CExternalTools::OutputTextToImage(imgOutput, strTemp, 4, 4, 255, 255, 255, 255, 0, 0);

									sprintf_s(strTemp, "%sConfidence.%s.%s.%04d.jpg",
										GlobalHiBoostSettings.GetPN_BoostDetect_SingleNode(i_node).c_str(),
										GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
										GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
										i_image);
									CExternalTools::mySaveImage(strTemp, imgOutput);
								}
							} // i_node

							if (!(Op_BoostDetect & 1))
							{
								sprintf_s(strTemp, "Detect %s %s %04d / %04d; [%s per image];",
									GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
									GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
									i_image, Amount_SrcImage,
									CExternalTools::GetTimeText(timDetect.GetCumulativeTime() / count_image));
								CExternalTools::ConsoleTools::ClearCurrentLine();
								cout<<strTemp;
								outLog<<strTemp<<endl;
							}
						} // i_image
					} // sgnPosNeg

					for ( i_node = 0; i_node < AbstractTree.NodeAmount; ++i_node )
					{
						if (TargetNodeIndex>=0 && i_node!=TargetNodeIndex) continue;
						if (TargetNodeIndex<0 && !fNodeSelectedList.pElement[i_node]) continue;

						CBinaryClassificationResult_ByConfidence& cur_bcrc = bcrcList.pElement[i_node];
						sprintf_s(strTemp, "%sDetectPRC.Node.%02d.txt",
							GlobalHiBoostSettings.GetPN_BoostDetect_SingleNode(i_node).c_str(),
							i_node);
						cur_bcrc.Analyse();
						ofstream outFile(strTemp);
						cur_bcrc.OutputPRCtoStream(outFile, 100, 0.0, 1.0, false);
						outFile.clear();
						outFile.close();
					}
				} // sgnImageSet

				CDataStructureTools::MyRelease_Single(pIPPFE);
			} // (Op_BoostDetect & 1)

			if (Op_PerceptronDetect & 3)
			{
				if (Op_PerceptronDetect & 2)
					CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Perceptron_ImageCache);

				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Perceptron_DetectBase);
				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.strPN_Perceptron_ParseLog_Detect, true);

				CProposalTree ProposalTree;
				ProposalTree.ReadAndOrTreeModel(GlobalHiBoostSettings.strFN_Perceptron_ModelForDetect);
				if (TargetNodeIndex>=0 && TargetNodeIndex<AbstractTree.NodeAmount) ProposalTree.model.Root = TargetNodeIndex;
				ProposalTree.PrepareModel();

				CProposalTree ppt;
				ppt.ReadAndOrTreeModel(strFN_Perceptron_InitializedModel);
				ppt.PrepareModel();

				int root_node = ProposalTree.model.Root;

				CExternalTools::ConsoleTools::MakeDirectory(GlobalHiBoostSettings.GetPN_PerceptronDetect_SingleNode(root_node));
				const CBicExampleConfig& CurrentBicEC = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(root_node);

				double TARGET_RECALL = CParameter().m_Recalls[0]; // 0.95;
				double OUTPUT_SCALE = 1.0;

				CSimpleTypeArray<InstanceTreeType> InstTreeList;
				for ( sgnImageSet = 0; sgnImageSet < 2; ++sgnImageSet )
				{
					if (sgnImageSet==0 && !(Flag_Detect_ImageSet & 1)) continue;
					if (sgnImageSet==1 && !(Flag_Detect_ImageSet & 2)) continue;

					CHiBoostGroundTruthList* pCurrent_GT_List;
					string strPN_SaveGT = "";
					string strPN_LoadGT = "";
					string strPN_DrawGT = "";
					if (sgnImageSet==0) // (1)
					{
						pCurrent_GT_List = &GT_List_Train;
						strPN_LoadGT = strPN_Perceptron_GT_Instance_Train;
						if (Op_PerceptronDetect & 1)
						{
							strPN_SaveGT = strPN_Perceptron_GT_Instance_Train;
							strPN_DrawGT = strPN_Perceptron_GT_Image_Train;
						}
					}
					else
					{
						pCurrent_GT_List = &GT_List_Test;
						strPN_LoadGT = strPN_Perceptron_GT_Instance_Test;
						if (Op_PerceptronDetect & 1)
						{
							strPN_SaveGT = strPN_Perceptron_GT_Instance_Test;
							strPN_DrawGT = strPN_Perceptron_GT_Image_Test;
						}
					}
					
					ProposalTree.ParseGroundTruthList(InstTreeList, *pCurrent_GT_List, true, strPN_LoadGT, strPN_SaveGT, strPN_DrawGT);

					if (Op_PerceptronDetect & 2)
					{
						// Refresh Ground Truth List & Parsing Threshold List
						for ( int i_gt = 0; i_gt < (int)InstTreeList.Size; ++i_gt )
						{
							InstanceTreeType& CurrentInstGT = InstTreeList.pElement[i_gt];
							ProposalTree.RefreshMRFScore(CurrentInstGT);
						}
						sgnImageSet = sgnImageSet;
						ProposalTree.SetAndNodeThreshold(InstTreeList, TARGET_RECALL);

						double TargetCT = ProposalTree.model.AndModels[root_node].Threshold[0];

						sprintf_s(strTemp, "Root Target Recall = %.2lf%%, CT = %.4lf;", TARGET_RECALL * 100.0, TargetCT);
						CExternalTools::ConsoleTools::MakeCurrentLine(strTemp, true);
						CExternalTools::ConsoleTools::OutputTextToStream(outLog, strTemp, true);

						MeanShiftConfig_ForPerceptronDetect.SetConfidenceThreshold(TargetCT);

						const CHiBoostGroundTruthList* pCurrent_GT_List;
						if (sgnImageSet == 0) pCurrent_GT_List = &GT_List_Train;
						if (sgnImageSet == 1) pCurrent_GT_List = &GT_List_Test;
						int i_pGT = 0;

						CTimer timDetect;
						timDetect.Reset();
						double tcIATC = 0.0;

						int count_image = 0;

						CBinaryClassificationResult_ByConfidence bcrc;
						bcrc.Clear();

						int j_node;
						CSimpleTypeArray<CBinaryClassificationResult_ByPrediction> bcrpList;
						bcrpList.Resize(AbstractTree.NodeAmount);
						for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node )
							bcrpList.pElement[j_node].Clear();

						for ( sgnPosNeg = 1; sgnPosNeg >= 0; --sgnPosNeg )
						//for ( sgnPosNeg = 0; sgnPosNeg < 2; ++sgnPosNeg )
						{
							if (sgnPosNeg==1 && !(Flag_Detect_PosNeg & 1)) continue;
							if (sgnPosNeg==0 && !(Flag_Detect_PosNeg & 2)) continue;

							int Amount_SrcImage = GlobalHiBoostSettings.GetAmount_SrcImage(sgnImageSet, sgnPosNeg);
							for ( i_image = 0; i_image < Amount_SrcImage; ++i_image )
							{
								CImg<int> imgSrc;
								GlobalHiBoostSettings.MakeFN_SrcImage(strTemp, sgnImageSet, sgnPosNeg, i_image);
								CExternalTools::myLoadImage(strTemp, imgSrc);
								++count_image;

								CSimpleTypeArray<CSimpleTypeArray<CMyNodeInstance>> matMNI;
								matMNI.Resize(AbstractTree.NodeAmount);

								CSimpleTypeArray<CCandidateDetection> CanDetList;
								CSimpleTypeArray<CCandidateDetection> ReducedDetList;
								CSimpleTypeArray<CDetectionWithScore> MyDetList;
								CSimpleTypeArray<CDetectionWithScore> GtDetList;
								CDetectionWithScore tDetetionWithScore;

								CHiBoostImageEntity iEntity;
								CHiBoostGroundTruth iGT;
								InstanceTreeType iTree;
								CMyTreeInstance iMTI;
								CRectBox<double> dBox;
								CHiBoostImageEntity::CGtNodeInst tGtNodeInst;

								CImg<int> imgOutput;

								timDetect.Start();
								iEntity.SetImage(imgSrc,
									GlobalHiBoostSettings.GetPerceptronImageHashName(sgnImageSet, sgnPosNeg, i_image),
									false);

								GtDetList.Clear();
								for ( ; (sgnPosNeg==1 && i_pGT<pCurrent_GT_List->Amount_GroundTruth); ++i_pGT )
								{
									iGT = pCurrent_GT_List->GroundTruthList.pElement[i_pGT];
									if (iGT.MaterialIndex < i_image) continue;
									if (iGT.MaterialIndex > i_image) break;
									if (iGT.fIsFlipped) continue;

									iEntity.ReadParsedLeafInstances(&iGT);
									ppt.ParseEntityGroundTruth(iTree, iEntity, false);

									ppt.MakeMyTreeInstance(iMTI, iTree, 0, iEntity);

									for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node )
									{
										CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[j_node];
										if (tMNI.fIsMissing) continue;
										tGtNodeInst.x = tMNI.x;
										tGtNodeInst.y = tMNI.y;
										tGtNodeInst.rot = tMNI.rot;
										tGtNodeInst.scale = tMNI.scale;
										iEntity.matGtNodeInst.pElement[j_node].PushBack(tGtNodeInst);
									}

									CMyNodeInstance& tMNI = iMTI.NodeInstanceList.pElement[root_node];
									CurrentBicEC.MakeTightBoxFromCenterAndIplScale(dBox, tMNI.x, tMNI.y, 1.0/tMNI.scale);
									tDetetionWithScore.Detection = dBox;
									tDetetionWithScore.fIsMatched = false;
									tDetetionWithScore.Score = 0.0;
									GtDetList.PushBack(tDetetionWithScore);
								} // i_pGT

								for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node ) matMNI.pElement[j_node].Clear();
								CanDetList.Clear();
								for ( i_layer = 0; ; ++i_layer )
								{
									if (!iEntity.SetCurrentImageLayer(i_layer)) break;

									string strCurrentParseLog = GlobalHiBoostSettings.GetPN_PerceptronDetect_ParseLog(sgnImageSet, sgnPosNeg, i_image, i_layer);
									CExternalTools::ConsoleTools::MakeDirectory(strCurrentParseLog);

									iEntity.CurrentImageLayer.DrawPixSet(imgOutput);
									sprintf_s(strTemp, "%sPixSet.jpg", strCurrentParseLog.c_str());
									CExternalTools::mySaveImage(strTemp, imgOutput);

									ProposalTree.ParseEntityCurrentLayer(iTree, iEntity, strCurrentParseLog);
									j_node = 0;

									for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node)
									{
										if (!ProposalTree.model.List_fIfNodeWork[j_node]) continue;
										ProposalTree.MakeMyNodeInstanceList(matMNI.pElement[j_node], true, false, j_node, iTree, iEntity);
									}
									ProposalTree.MakeCanDetList(CanDetList, true, false, root_node, iTree, iEntity);
								}

								for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node)
								{
									if (!ProposalTree.model.List_fIfNodeWork[j_node]) continue;

									int amount_gt_node_inst = (int)iEntity.matGtNodeInst.pElement[j_node].Size;
									CHiBoostImageEntity::CGtNodeInst* pGtNodeInstBase = iEntity.matGtNodeInst.pElement[j_node].pElement;

									int amount_mni = (int)matMNI.pElement[j_node].Size;
									CMyNodeInstance* p_MNI_Base = matMNI.pElement[j_node].pElement;
									
									int ii, jj;
									NodeInstanceType ni_gt, ni_cd;

#if 1
									CImagePyramidPosition t_ipp;
									CDetectionWithScore t_dws;
									CSimpleTypeArray<CDetectionWithScore> v_GT;
									CSimpleTypeArray<CDetectionWithScore> v_NI;
									v_GT.Clear(); v_NI.Clear();
									const CBicExampleConfig& j_BicEC = GlobalHiBoostSettings.HiBoostExampleSettings.GetNodeBicExampleConfig(j_node);

									for ( ii = 0; ii < amount_gt_node_inst; ++ii )
									{
										t_ipp.InitNew(pGtNodeInstBase[ii].x, pGtNodeInstBase[ii].y, 1.0 / pGtNodeInstBase[ii].scale, 1.0 / pGtNodeInstBase[ii].scale);
										j_BicEC.MakeTightBoxFromExample(t_dws.Detection, t_ipp);
										t_dws.Score = 0.0;
										v_GT.PushBack(t_dws);
									}
									for ( jj = 0; jj < amount_mni; ++jj )
									{
										t_ipp.InitNew(p_MNI_Base[jj].x, p_MNI_Base[jj].y, 1.0 / p_MNI_Base[jj].scale, 1.0 / p_MNI_Base[jj].scale);
										j_BicEC.MakeTightBoxFromExample(t_dws.Detection, t_ipp);
										t_dws.Score = 0.0;
										v_NI.PushBack(t_dws);
									}
									CDetectionWithScore::CheckDetections(v_NI, v_GT, 0.50, true);
									for ( ii = 0; ii < amount_gt_node_inst; ++ii )
										bcrpList.pElement[j_node].NewTest(+1, (v_GT.pElement[ii].fIsMatched ? +1 : -1), 1.0);
									bcrpList.pElement[j_node].Analyse();
#else
									for ( ii = 0; ii < amount_gt_node_inst; ++ii )
									{
										ni_gt.center.x = pGtNodeInstBase[ii].x;
										ni_gt.center.y = pGtNodeInstBase[ii].y;
										ni_gt.center.ori = pGtNodeInstBase[ii].rot;
										ni_gt.center.scale = pGtNodeInstBase[ii].scale;
										for ( jj = 0; jj < amount_mni; ++jj )
										{
											ni_cd.center.x = p_MNI_Base[jj].x;
											ni_cd.center.y = p_MNI_Base[jj].y;
											ni_cd.center.ori = p_MNI_Base[jj].rot;
											ni_cd.center.scale = p_MNI_Base[jj].scale;
											if (CAndNode::InstanceSimilar(ProposalTree.model, j_node, ni_gt, ni_cd)) break;
										}
										bcrpList.pElement[j_node].NewTest(+1, (jj<amount_mni ? +1 : -1), 1.0);
									}
									bcrpList.pElement[j_node].Analyse();
#endif
								}

								CMeanShiftNMS msNMS;
								int i_det, i_gt;

								msNMS.myInit(MeanShiftConfig_ForPerceptronDetect, NULL, NULL);

								sort(CanDetList.Begin(), CanDetList.End(), CCandidateDetection::CompareBy_Bigger_Confidence);
								{
									int i_cd, i_rd;
									CRectBox<double> b_cd, b_rd;
									double t_AOP;
									double t_AO, t_a_cd, t_a_rd;
									t_AOP = t_AO = 0.0;

									ReducedDetList.Clear();
									for ( i_cd = 0; i_cd < (int)CanDetList.Size; ++i_cd )
									{
										const CCandidateDetection& t_cd = CanDetList.pElement[i_cd];
										CurrentBicEC.MakeTightBoxFromExample(b_cd, t_cd.ipp);
										t_a_cd = b_cd.CalcArea();

										for ( i_rd = 0; i_rd < (int)ReducedDetList.Size; ++i_rd )
										{
											const CCandidateDetection& t_rd = ReducedDetList.pElement[i_rd];
											CurrentBicEC.MakeTightBoxFromExample(b_rd, t_rd.ipp);
											t_a_rd = b_rd.CalcArea();
											
											t_AOP = CRectBox<double>::CalcAO_Percent(b_cd, b_rd);
											if (t_AOP > 0.50) break;

											t_AO = CRectBox<double>::CalcAreaOfOverlap(b_cd, b_rd);
											t_AO /= (t_a_cd<t_a_rd ? t_a_cd : t_a_rd); // t_a_cd; // (t_a_cd<t_a_rd ? t_a_cd : t_a_rd);
											if (t_AO > 0.50) break;
										}
										if (i_rd < (int)ReducedDetList.Size) continue;
										ReducedDetList.PushBack(t_cd);
									}
								}

								//msNMS.DoNMS(ReducedDetList, CanDetList);
								//ReducedDetList = CanDetList;

								MyDetList.Resize(ReducedDetList.Size);
								for ( int i_det = 0; i_det < (int)ReducedDetList.Size; ++i_det )
								{
									const CCandidateDetection& ttt = ReducedDetList.pElement[i_det];
									CurrentBicEC.MakeTightBoxFromExample(tDetetionWithScore.Detection, ttt.ipp);
									tDetetionWithScore.Score = ttt.Confidence;
									tDetetionWithScore.fIsMatched = false;
									MyDetList.pElement[i_det] = tDetetionWithScore;
								}
								sort(MyDetList.Begin(), MyDetList.End());

								timDetect.Stop();

								bcrc.ExtraFalseNegAmount += CDetectionWithScore::CheckDetections(MyDetList, GtDetList);

								CZoomConfig zc = iEntity.ZoomImage.BuildImage(imgOutput, OUTPUT_SCALE, OUTPUT_SCALE, CDenseImage::EXPANDING_MODE_EDGE);
								int _color;
								for ( i_gt = 0; i_gt < (int)GtDetList.Size; ++i_gt )
								{
									zc.WorkOnBox(dBox, GtDetList.pElement[i_gt].Detection);
									_color = 0x00ffff00;
									CExternalTools::DrawRectBox(imgOutput, dBox, _color);
								}
								for ( i_det = 0; i_det < (int)MyDetList.Size; ++i_det )
								{
									tDetetionWithScore = MyDetList.pElement[i_det];
									(tDetetionWithScore.fIsMatched ? bcrc.Pos : bcrc.Neg).PushBack(tDetetionWithScore.Score);

									zc.WorkOnBox(dBox, tDetetionWithScore.Detection);
									_color = (tDetetionWithScore.fIsMatched ? 0x0000ff00 : 0x00ff0000);
									CExternalTools::DrawRectBox(imgOutput, dBox, _color);

									double ts = tDetetionWithScore.Score;
									//if (ts > -100) ts = -log(exp(-ts)-1);
									sprintf_s(strTemp, "%.4lf", ts);
									CExternalTools::OutputTextToImage(imgOutput, strTemp,
										(int)dBox.x, (int)dBox.y,
										((_color>>16)&255), ((_color>>8)&255), ((_color>>0)&255),
										0, 0, 0);
								}

								bcrc.Analyse();
								double CurrentAP = bcrc.Get_AveragePrecision();

								sprintf_s(strTemp, "Current AP = %.2lf%%;", CurrentAP * 100.0);
								int zh = 2;
								CExternalTools::OutputTextToImage(imgOutput, strTemp, 2, zh, 255, 255, 255, 0, 0, 0);
								for ( j_node = 0; j_node < AbstractTree.NodeAmount; ++j_node)
								{
									if (!ProposalTree.model.List_fIfNodeWork[j_node]) continue;
									zh += 10;
									sprintf_s(strTemp, "Node %02d Recall = %.2lf%% [%d/%d];",
										j_node,
										bcrpList.pElement[j_node].DetectionRate * 100.0,
										bcrpList.pElement[j_node]._TruePosAmount,
										bcrpList.pElement[j_node]._PosAmount);
									CExternalTools::OutputTextToImage(imgOutput, strTemp, 2, zh, 255, 255, 255, 0, 0, 0);
								}

								sprintf_s(strTemp, "%sDetection.%s.%s.%04d.jpg",
									GlobalHiBoostSettings.GetPN_PerceptronDetect_SingleNode(root_node).c_str(),
									GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
									GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
									i_image);
								CExternalTools::mySaveImage(strTemp, imgOutput);

								tcIATC += iEntity.timAppCalc.GetCumulativeTime();
								string strISTC = CExternalTools::GetTimeText((timDetect.GetCumulativeTime() - tcIATC) / count_image);
								string strIATC = CExternalTools::GetTimeText(tcIATC / count_image);
								sprintf_s(strTemp, "%s %s %04d/%04d; S:A ITC = [%s : %s]; N.%02d AP = %.2lf%%;",
									GlobalHiBoostSettings.GetText_ImageSet(sgnImageSet),
									GlobalHiBoostSettings.GetText_PosNeg(sgnPosNeg),
									i_image, Amount_SrcImage,
									strISTC.c_str(), strIATC.c_str(),
									root_node, CurrentAP * 99.99);
								CExternalTools::ConsoleTools::ClearCurrentLine();
								cout<<strTemp<<endl;
								outLog<<strTemp<<endl;
							} // i_image
						} // sgnPosNeg

						bcrc.Analyse();
						sprintf_s(strTemp, "%sPerceptronDetectPRC.txt",
							GlobalHiBoostSettings.GetPN_PerceptronDetect_SingleNode(root_node).c_str());
						ofstream outFile_PRC(strTemp);
						bcrc.OutputPRCtoStream(outFile_PRC, 100, 0.0, 1.0, false);
						outFile_PRC.clear();
						outFile_PRC.close();
					} // (Op_PerceptronDetect & 2)
				} // sgnImageSet
			} // (Op_PerceptronDetect & 3)
		}
		// ********** Main Code Finish **********

		outLog.clear();
		outLog.close();

		//CDataStructureTools::MyRelease_Single(pIFB_HiBoost);
	}

	CImageEx::Release();
	return nRetCode;
}

